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

📄 usb2com.pnp.cpp

📁 这是一个关于USB转接串口的驱动程序开发
💻 CPP
字号:
//********************************************************************
//	created:	11:7:2008   21:30
//	file:		usb2com.pnp.cpp
//	author:		tiamo
//	purpose:	pnp
//********************************************************************

#include "stdafx.h"

//
// pnp complete routine
//
NTSTATUS Usb2ComPnpCompleteRoutine(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp,__in PVOID Context)
{
	PRKEVENT Event										= static_cast<PRKEVENT>(Context);

	KeSetEvent(Event,IO_NO_INCREMENT,FALSE);

	return STATUS_MORE_PROCESSING_REQUIRED;
}

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

	//
	// acquire remove lock
	//
	NTSTATUS Status										= IoAcquireRemoveLock(&DevExt->RemoveLock,Irp);
	if(!NT_SUCCESS(Status))
	{
		//
		// IoAcquireRemoveLock will fail only if we have already processed IRP_MN_REMOVE_DEVICE,
		// if we got here,it means someone sent us a pnp request after remove.
		//
		ASSERT(FALSE);
		Irp->IoStatus.Status							= Status;
		Irp->IoStatus.Information						= 0;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);
		return Status;
	}

	//
	// we initialize status with the value in the irp
	//
	Status												= Irp->IoStatus.Status;

	switch(IrpSp->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
		Status											= Usb2ComStartDevice(DevExt,Irp,IrpSp);
		break;

	case IRP_MN_REMOVE_DEVICE:
		//
		// remove device
		//
		Usb2ComRemoveDevice(DevExt,Irp,IrpSp,FALSE);

		//
		// call lower driver
		//
		IoCopyCurrentIrpStackLocationToNext(Irp);
		Status											= IoCallDriver(DevExt->LowerDeviceObject,Irp);

		//
		// wait all outgoing irp to complete
		//
		IoReleaseRemoveLockAndWait(&DevExt->RemoveLock,Irp);

		//
		// cleanup fdo
		//
		Usb2ComCleanupFunctionDeviceObject(DeviceObject);

		//
		// return to our caller,do NOT call ReleaseRemoveLock
		//
		return Status;
		break;

	case IRP_MN_STOP_DEVICE:
		Status										= Usb2ComStopDevice(DevExt,Irp,IrpSp);
		break;

	case IRP_MN_QUERY_STOP_DEVICE:
		if(DevExt->BulkOutUrbIsRunning || DevExt->BulkInUrbIsRunning || DevExt->InterruptUrbIsRunning)
		{
			Status									= STATUS_UNSUCCESSFUL;
			Irp->IoStatus.Status					= Status;
			Irp->IoStatus.Information				= 0;
			IoCompleteRequest(Irp,IO_NO_INCREMENT);
		}
		else
		{
			IoSkipCurrentIrpStackLocation(Irp);
			Status										= IoCallDriver(DevExt->LowerDeviceObject,Irp);
		}
		break;

	case IRP_MN_QUERY_CAPABILITIES:
		Status										= Usb2ComQueryCapabilities(DevExt,Irp,IrpSp);
		break;

	case IRP_MN_SURPRISE_REMOVAL:
		//
		// remove device
		//
		Usb2ComRemoveDevice(DevExt,Irp,IrpSp,TRUE);

		//
		// pass the irp to the lower driver,we should NOT delete the device object here.
		// pnp manager will send us another remove request in the later time,we will delete it in the remove quest
		// fail through to the default handler
		//

	default:
		IoSkipCurrentIrpStackLocation(Irp);
		Status										= IoCallDriver(DevExt->LowerDeviceObject,Irp);
		break;
	}

	IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);

	return Status;
}

//
// start device
//
NTSTATUS Usb2ComStartDevice(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp)
{
	//
	// initialize an event
	//
	KEVENT Event;
	KeInitializeEvent(&Event,NotificationEvent,FALSE);

	//
	// call the next driver
	//
	IoCopyCurrentIrpStackLocationToNext(Irp);
	IoSetCompletionRoutine(Irp,&Usb2ComPnpCompleteRoutine,&Event,TRUE,TRUE,TRUE);
	NTSTATUS Status										= IoCallDriver(DevExt->LowerDeviceObject,Irp);
	if(Status == STATUS_PENDING)
	{
		KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,0);
		Status											= Irp->IoStatus.Status;
	}

	//
	// start ourself iff the lower device started successfully
	//
	if(NT_SUCCESS(Status))
	{
		//
		// config usb device
		//
		Status											= Usb2ComConfigUsbDevice(DevExt);
		if(NT_SUCCESS(Status))
		{
			Status										= Usb2ComInitializeFIFOControl(DevExt);
			if(NT_SUCCESS(Status))
			{
				//
				// enable device interface
				//
				Status									= IoSetDeviceInterfaceState(&DevExt->SymbolicLinkName,TRUE);

				//
				// setup com params
				//
				DevExt->Baudrate						= 115200;
				DevExt->SerialChars.BreakChar			= 0;
				DevExt->SerialChars.EofChar				= 0;
				DevExt->SerialChars.ErrorChar			= 0;
				DevExt->SerialChars.EventChar			= 0;
				DevExt->SerialChars.XoffChar			= 0x13;
				DevExt->SerialChars.XonChar				= 0x11;
				DevExt->SerialCommProp.CurrentRxQueue	= 0x2000;
				DevExt->SerialCommProp.CurrentTxQueue	= 0;
				DevExt->SerialCommProp.MaxBaud			= SERIAL_BAUD_USER;
				DevExt->SerialCommProp.MaxRxQueue		= 0;
				DevExt->SerialCommProp.MaxTxQueue		= 0;
				DevExt->SerialCommProp.PacketLength		= sizeof(SERIAL_COMMPROP);
				DevExt->SerialCommProp.PacketVersion	= 2;
				DevExt->SerialCommProp.ProvCapabilities	= SERIAL_PCF_DTRDSR | SERIAL_PCF_RTSCTS | SERIAL_PCF_CD | SERIAL_PCF_PARITY_CHECK | 
														  SERIAL_PCF_XONXOFF | SERIAL_PCF_SETXCHAR | SERIAL_PCF_TOTALTIMEOUTS | SERIAL_PCF_INTTIMEOUTS;
				DevExt->SerialCommProp.ProvChar[0]		= 0;
				DevExt->SerialCommProp.ProvSpec1		= 0;
				DevExt->SerialCommProp.ProvSpec2		= 0;
				DevExt->SerialCommProp.ProvSubType		= SERIAL_SP_RS232;
				DevExt->SerialCommProp.Reserved1		= 0;
				DevExt->SerialCommProp.ServiceMask		= SERIAL_SP_SERIALCOMM;
				DevExt->SerialCommProp.SettableBaud		= SERIAL_BAUD_USER | SERIAL_BAUD_128K | SERIAL_BAUD_115200 | SERIAL_BAUD_57600 | SERIAL_BAUD_14400 | 
														  SERIAL_BAUD_19200 | SERIAL_BAUD_38400 | SERIAL_BAUD_56K | SERIAL_BAUD_2400 | SERIAL_BAUD_4800 | 
														  SERIAL_BAUD_7200 | SERIAL_BAUD_9600 | SERIAL_BAUD_300 | SERIAL_BAUD_600 | SERIAL_BAUD_1200 | 
														  SERIAL_BAUD_1800 | SERIAL_BAUD_075 | SERIAL_BAUD_110 | SERIAL_BAUD_150;
				DevExt->SerialCommProp.SettableData		= SERIAL_DATABITS_5 | SERIAL_DATABITS_6 | SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
				DevExt->SerialCommProp.SettableParams	= SERIAL_SP_PARITY | SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_STOPBITS |
														  SERIAL_SP_HANDSHAKING | SERIAL_SP_PARITY_CHECK | SERIAL_SP_CARRIER_DETECT;
				DevExt->SerialCommProp.SettableStopParity= SERIAL_STOPBITS_10 | SERIAL_STOPBITS_20 | SERIAL_PARITY_NONE | SERIAL_PARITY_ODD |
														   SERIAL_PARITY_EVEN | SERIAL_PARITY_MARK | SERIAL_PARITY_SPACE;
				DevExt->SerialHandFlow.ControlHandShake	= SERIAL_DTR_CONTROL;
				DevExt->SerialHandFlow.FlowReplace		= SERIAL_RTS_CONTROL;
				DevExt->SerialHandFlow.XoffLimit		= 0x400;
				DevExt->SerialHandFlow.XonLimit			= 0x1000;
				DevExt->SerialLineControl.Parity		= 0;
				DevExt->SerialLineControl.StopBits		= 1;
				DevExt->SerialLineControl.WordLength	= 8;
				DevExt->SerialQueueSize.InSize			= 0x1000;
				DevExt->SerialQueueSize.OutSize			= 0x400;
				RtlZeroMemory(&DevExt->SerialStats,sizeof(DevExt->SerialStats));
				RtlZeroMemory(&DevExt->SerialStatus,sizeof(DevExt->SerialStatus));
			}
		}
	}

	//
	// complete this request
	//
	Irp->IoStatus.Status								= Status;
	Irp->IoStatus.Information							= 0;
	IoCompleteRequest(Irp,IO_NO_INCREMENT);
	return Status;
}

//
// stop device
//
NTSTATUS Usb2ComStopDevice(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp)
{
	//
	// complete all irps with canceled status
	//
	Usb2ComCancelAllIrps(DevExt);

	//
	// disable usb device
	//
	Usb2ComDisableUsbDevice(DevExt);

	return STATUS_SUCCESS;
}

NTSTATUS Usb2ComRemoveDevice(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp,__in BOOLEAN SurpriseRemoval)
{
	Usb2ComCancelAllIrps(DevExt);

	if(SurpriseRemoval)
		DevExt->SurpriseRemoved							= TRUE;

	//
	// if this is a surprise remove or we got a remove without a surprise remove
	// then we need to clean up
	//
	if(SurpriseRemoval || !DevExt->SurpriseRemoved)
		IoSetDeviceInterfaceState(&DevExt->SymbolicLinkName,FALSE);

	return STATUS_SUCCESS;
}

//
// query capabilities
//
NTSTATUS Usb2ComQueryCapabilities(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp)
{
	//
	// initialize an event
	//
	KEVENT Event;
	KeInitializeEvent(&Event,NotificationEvent,FALSE);

	//
	// call the next driver
	//
	IoCopyCurrentIrpStackLocationToNext(Irp);
	IoSetCompletionRoutine(Irp,&Usb2ComPnpCompleteRoutine,&Event,TRUE,TRUE,TRUE);
	NTSTATUS Status										= IoCallDriver(DevExt->LowerDeviceObject,Irp);
	if(Status == STATUS_PENDING)
	{
		KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,0);
		Status											= Irp->IoStatus.Status;
	}

	if(NT_SUCCESS(Status))
	{
		PDEVICE_CAPABILITIES Capabilities				= IrpSp->Parameters.DeviceCapabilities.Capabilities;
		if(Capabilities)
		{
			Capabilities->EjectSupported				= TRUE;
			Capabilities->Removable						= TRUE;
			Capabilities->SurpriseRemovalOK				= TRUE;
			Capabilities->WarmEjectSupported			= TRUE;
			RtlCopyMemory(&DevExt->DeviceCapabilities,Capabilities,sizeof(DEVICE_CAPABILITIES));
		}
	}

	IoCompleteRequest(Irp,IO_NO_INCREMENT);

	return Status;
}

⌨️ 快捷键说明

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