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

📄 usb2com.create.cpp

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

#include "stdafx.h"

//
// create dispatch routine
//
NTSTATUS Usb2ComCreate(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
	PUSB2COM_DEVICE_EXTENSION DevExt					= static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);

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

		return Status;
	}

	//
	// already opened
	//
	if(TRUE == InterlockedCompareExchange(&DevExt->DeviceIsOpened,TRUE,FALSE))
	{
		Irp->IoStatus.Status							= STATUS_ACCESS_DENIED;
		Irp->IoStatus.Information						= 0;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);

		IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);

		return STATUS_ACCESS_DENIED;
	}

	DevExt->TxHoldReason								= 0;
	DevExt->RxHoldReason								= 0;
	DevExt->Baudrate									= 115200;
	DevExt->SerialLineControl.Parity					= 0;
	DevExt->SerialLineControl.StopBits					= 1;
	DevExt->SerialLineControl.WordLength				= 8;
	DevExt->ReadBufferCharsCount						= 0;
	DevExt->FirstReadCharSlot							= 0;
	InterlockedIncrement(&DevExt->CurrentWriteIrpSignature);
	DevExt->WriteBuffer									= 0;
	DevExt->WriteBufferLength							= 0;
	DevExt->WriteBufferOffset							= 0;
	DevExt->ForceBulkInUrbStop							= FALSE;
	DevExt->ForceBulkOutUrbStop							= FALSE;
	DevExt->ForceInterruptUrbStop						= FALSE;

	Usb2ComSetBaudrate(DevExt);

	Usb2ComSetLineControl(DevExt);

	Usb2ComClearDTR(DevExt);

	Usb2ComClearRTS(DevExt);

	Usb2ComSetDTR(DevExt);

	Usb2ComSetRTS(DevExt);

	Usb2ComRecvVendorRequest(DevExt,0x06,&DevExt->ModemStatus);

	DevExt->ModemStatus									&= 0xf0;

	Usb2ComStartBulkInUrb(DevExt,FALSE,0);

	Usb2ComStartInterruptUrb(DevExt,FALSE,0);

	Irp->IoStatus.Status								= STATUS_SUCCESS;
	Irp->IoStatus.Information							= FILE_OPENED;

	IoCompleteRequest(Irp,IO_NO_INCREMENT);

	IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);

	return STATUS_SUCCESS;
}

//
// interrupt urb complete routine
//
NTSTATUS Usb2ComInterruptUrbComplete(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp,__in PVOID Context)
{
	PUSB2COM_DEVICE_EXTENSION DevExt					= static_cast<PUSB2COM_DEVICE_EXTENSION>(Context);
	NTSTATUS Status										= Irp->IoStatus.Status;
	PURB Urb											= DevExt->InterruptUrb;
	PUCHAR Buffer										= static_cast<PUCHAR>(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
	ULONG EventFlags									= 0;

	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->InterruptLock,&SavedIrql);

	//
	// current interrupt urb is finished
	//
	DevExt->InterruptUrbIsRunning						= FALSE;

	if(NT_SUCCESS(Status))
	{
		if(Buffer[0] == 0xe8)
		{
			UCHAR ModemStatus							= Buffer[3] & 0xf0;

			if((DevExt->SerialHandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) && !(ModemStatus & 0x10))
				DevExt->TxHoldReason					|= SERIAL_TX_CTS;
			else
				DevExt->TxHoldReason					&= ~SERIAL_TX_CTS;

			if((DevExt->SerialHandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) && !(ModemStatus & 0x20))
				DevExt->TxHoldReason					|= SERIAL_TX_DSR;
			else
				DevExt->TxHoldReason					&= ~SERIAL_TX_DSR;

			if((DevExt->SerialHandFlow.ControlHandShake & SERIAL_DCD_HANDSHAKE) && !(ModemStatus & 0x80))
				DevExt->TxHoldReason					|= SERIAL_TX_DCD;
			else
				DevExt->TxHoldReason					&= ~SERIAL_TX_DCD;

			if((DevExt->SerialHandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) && !(ModemStatus & 0x20))
				DevExt->RxHoldReason					|= SERIAL_RX_DSR;
			else
				DevExt->RxHoldReason					&= ~SERIAL_RX_DSR;

			DevExt->ModemStatus							= ModemStatus;

			ModemStatus									= Buffer[3];

			if(ModemStatus & 0x01)
				EventFlags								|= SERIAL_EV_CTS;

			if(ModemStatus & 0x02)
				EventFlags								|= SERIAL_EV_DSR;

			if(ModemStatus & 0x04)
				EventFlags								|= SERIAL_EV_RING;

			if(ModemStatus & 0x08)
				EventFlags								|= SERIAL_EV_RLSD;
		}
	}

	Usb2ComStartInterruptUrb(DevExt,TRUE,SavedIrql);

	Usb2ComStartBulkInUrb(DevExt,FALSE,0);

	Usb2ComStartBulkOutUrb(DevExt,FALSE,0);

	if(EventFlags)
		Usb2ComProcessEvent(DevExt,EventFlags);

	return STATUS_MORE_PROCESSING_REQUIRED;
}

//
// send interrupt urb
//
VOID Usb2ComStartInterruptUrb(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in BOOLEAN AlreadyLocked,__in KIRQL SavedIrql)
{
	BOOLEAN ReleaseLock									= TRUE;

	__try
	{
		//
		// acquire interrupt lock
		//
		if(!AlreadyLocked)
			KeAcquireSpinLock(&DevExt->InterruptLock,&SavedIrql);

		//
		// check interrupt urb is running
		//
		if(!DevExt->InterruptUrbIsRunning)
		{
			//
			// reuse interrupt irp
			//
			IoReuseIrp(DevExt->InterruptIrp,STATUS_SUCCESS);

			//
			// short ok?
			//
			UsbBuildInterruptOrBulkTransferRequest(DevExt->InterruptUrb,sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),DevExt->UsbInterfaceInfo->Pipes[0].PipeHandle,
												   DevExt->InterruptBuffer,0,0x04,USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,0);

			PIO_STACK_LOCATION NextIrpSp				= IoGetNextIrpStackLocation(DevExt->InterruptIrp);
			NextIrpSp->MajorFunction					= IRP_MJ_INTERNAL_DEVICE_CONTROL;
			NextIrpSp->Parameters.Others.Argument1		= DevExt->InterruptUrb;
			NextIrpSp->Parameters.Others.Argument2		= 0;
			NextIrpSp->Parameters.Others.Argument3		= reinterpret_cast<PVOID>(IOCTL_INTERNAL_USB_SUBMIT_URB);
			NextIrpSp->Parameters.Others.Argument4		= 0;

			IoSetCompletionRoutine(DevExt->InterruptIrp,&Usb2ComInterruptUrbComplete,DevExt,TRUE,TRUE,TRUE);

			if(!DevExt->ForceInterruptUrbStop)
			{
				DevExt->InterruptUrbIsRunning			= TRUE;
				KeResetEvent(&DevExt->InterruptUrbStopEvent);

				KeReleaseSpinLock(&DevExt->InterruptLock,SavedIrql);
				ReleaseLock								= FALSE;

				IoCallDriver(DevExt->LowerDeviceObject,DevExt->InterruptIrp);
			}
		}
	}
	__finally
	{
		if(ReleaseLock)
		{
			BOOLEAN SetEvent							= !DevExt->InterruptUrbIsRunning;
			KeReleaseSpinLock(&DevExt->InterruptLock,SavedIrql);

			if(SetEvent)
				KeSetEvent(&DevExt->InterruptUrbStopEvent,IO_NO_INCREMENT,FALSE);
		}
	}
}

//
// stop interrupt urb
//
VOID Usb2ComStopInterruptUrb(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->InterruptLock,&SavedIrql);

	DevExt->ForceInterruptUrbStop						= TRUE;

	KeReleaseSpinLock(&DevExt->InterruptLock,SavedIrql);

	IoCancelIrp(DevExt->InterruptIrp);
}

//
// wait interrupt urb stop
//
VOID Usb2ComWaitInterruptUrbStopped(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
	KeWaitForSingleObject(&DevExt->InterruptUrbStopEvent,Executive,KernelMode,FALSE,0);
}

⌨️ 快捷键说明

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