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

📄 usb2com.devctrl.cpp

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

#include "stdafx.h"

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

	//
	// check pending remove
	//
	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;
	}

	ULONG InputLength									= IrpSp->Parameters.DeviceIoControl.InputBufferLength;
	ULONG OutputLength									= IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
	PVOID SystemBuffer									= Irp->AssociatedIrp.SystemBuffer;
	ULONG Information									= 0;
	Status												= STATUS_SUCCESS;

	switch(IrpSp->Parameters.DeviceIoControl.IoControlCode)
	{
	case IOCTL_SERIAL_CLEAR_STATS:
		{
			RtlZeroMemory(&DevExt->SerialStats,sizeof(SERIALPERF_STATS));
		}
		break;

	case IOCTL_SERIAL_CLR_DTR:
		{
			Status										= Usb2ComClearDTR(DevExt);
		}
		break;

	case IOCTL_SERIAL_CLR_RTS:
		{
			Status										= Usb2ComClearRTS(DevExt);
		}
		break;

	case IOCTL_SERIAL_CONFIG_SIZE:
		{
			if(OutputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(ULONG);
				*static_cast<PULONG>(SystemBuffer)		= 0;
			}
		}
		break;

	case IOCTL_SERIAL_GET_BAUD_RATE:
		{
			if(OutputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(ULONG);
				RtlCopyMemory(SystemBuffer,&DevExt->Baudrate,sizeof(ULONG));
			}
		}
		break;

	case IOCTL_SERIAL_GET_CHARS:
		{
			if(OutputLength < sizeof(SERIAL_CHARS))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(SERIAL_CHARS);
				RtlCopyMemory(SystemBuffer,&DevExt->SerialChars,sizeof(SERIAL_CHARS));
			}
		}
		break;

	case IOCTL_SERIAL_GET_COMMSTATUS:
		{
			if(OutputLength < sizeof(SERIAL_STATUS))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Status									= Usb2ComUpdateSerialStatus(DevExt);
				if(NT_SUCCESS(Status))
				{
					Information							= sizeof(SERIAL_STATUS);
					RtlCopyMemory(SystemBuffer,&DevExt->SerialStatus,sizeof(SERIAL_STATUS));
				}
			}
		}
		break;

	case IOCTL_SERIAL_GET_HANDFLOW:
		{
			if(OutputLength < sizeof(SERIAL_HANDFLOW))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(SERIAL_HANDFLOW);
				RtlCopyMemory(SystemBuffer,&DevExt->SerialHandFlow,sizeof(SERIAL_HANDFLOW));
			}
		}
		break;

	case IOCTL_SERIAL_GET_LINE_CONTROL:
		{
			if(OutputLength < sizeof(SERIAL_LINE_CONTROL))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(SERIAL_LINE_CONTROL);
				RtlCopyMemory(SystemBuffer,&DevExt->SerialLineControl,sizeof(SERIAL_LINE_CONTROL));
			}
		}
		break;

	case IOCTL_SERIAL_GET_MODEM_CONTROL:
		{
			if(OutputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Status									= Usb2ComGetModemControl(DevExt);
				if(NT_SUCCESS(Status))
				{
					Information							= sizeof(ULONG);
					*static_cast<PULONG>(SystemBuffer)	= DevExt->SerialModemControl;
				}
			}
		}
		break;

	case IOCTL_SERIAL_GET_MODEMSTATUS:
		{
			if(OutputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(ULONG);
				*static_cast<PULONG>(SystemBuffer)		= DevExt->ModemStatus;
			}
		}
		break;

	case IOCTL_SERIAL_GET_PROPERTIES:
		{
			if(OutputLength < sizeof(SERIAL_COMMPROP))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(SERIAL_COMMPROP);
				RtlCopyMemory(SystemBuffer,&DevExt->SerialCommProp,sizeof(SERIAL_COMMPROP));
				PSERIAL_COMMPROP Output					= static_cast<PSERIAL_COMMPROP>(SystemBuffer);
				Output->CurrentTxQueue					= DevExt->PendingWriteCharsCount;
			}
		}
		break;

	case IOCTL_SERIAL_GET_STATS:
		{
			if(OutputLength < sizeof(SERIALPERF_STATS))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(SERIALPERF_STATS);
				RtlCopyMemory(SystemBuffer,&DevExt->SerialStats,sizeof(SERIALPERF_STATS));
			}
		}
		break;

	case IOCTL_SERIAL_GET_TIMEOUTS:
		{
			if(OutputLength < sizeof(SERIAL_TIMEOUTS))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(SERIAL_TIMEOUTS);
				RtlCopyMemory(SystemBuffer,&DevExt->SerialTimeouts,sizeof(SERIAL_TIMEOUTS));
			}
		}
		break;

	case IOCTL_SERIAL_GET_WAIT_MASK:
		{
			if(OutputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				Information								= sizeof(ULONG);
				*static_cast<PULONG>(SystemBuffer)		= DevExt->CurrentWaitMask;
			}
		}
		break;

	case IOCTL_SERIAL_PURGE:
		{
			if(InputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				ULONG Mask								= *static_cast<PULONG>(SystemBuffer);
				Information								= sizeof(ULONG);

				if(Mask & SERIAL_PURGE_RXABORT)
				{
					Usb2ComCancelAllReadIrps(DevExt);
					Usb2ComResetReadBufferInfo(DevExt);
				}

				if(Mask & SERIAL_PURGE_TXABORT)
				{
					Usb2ComCancelAllWriteIrps(DevExt);
					DevExt->PendingWriteCharsCount		= 0;
				}
			}
		}
		break;

	case IOCTL_SERIAL_SET_BAUD_RATE:
		{
			if(InputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				DevExt->Baudrate						= *static_cast<PULONG>(Irp->AssociatedIrp.SystemBuffer);
				Status									= Usb2ComSetBaudrate(DevExt);
			}
		}
		break;

	case IOCTL_SERIAL_SET_BREAK_OFF:
		{
			Status										= Usb2ComSetBreakOff(DevExt);
		}
		break;

	case IOCTL_SERIAL_SET_BREAK_ON:
		{
			Status										= Usb2ComSetBreakOn(DevExt);
		}
		break;

	case IOCTL_SERIAL_SET_CHARS:
		{
			if(InputLength < sizeof(SERIAL_CHARS))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				PSERIAL_CHARS Input						= static_cast<PSERIAL_CHARS>(SystemBuffer);
				if(Input->XonChar == Input->XoffChar)
				{
					Status								= STATUS_INVALID_PARAMETER;
				}
				else
				{
					RtlCopyMemory(&DevExt->SerialChars,SystemBuffer,sizeof(SERIAL_CHARS));
				}
			}
		}
		break;

	case IOCTL_SERIAL_SET_DTR:
		{
			Status										= Usb2ComSetDTR(DevExt);
		}
		break;

	case IOCTL_SERIAL_SET_FIFO_CONTROL:
		{
			if(InputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				DevExt->SerialFIFOControl				= *static_cast<PUCHAR>(SystemBuffer);
				Status									= Usb2ComSetFIFOControl(DevExt);
			}
		}
		break;

	case IOCTL_SERIAL_SET_HANDFLOW:
		{
			if(InputLength < sizeof(SERIAL_HANDFLOW))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				PSERIAL_HANDFLOW Input					= static_cast<PSERIAL_HANDFLOW>(SystemBuffer);
				if( (Input->ControlHandShake & SERIAL_CONTROL_INVALID) || (Input->FlowReplace & SERIAL_FLOW_INVALID) || 
					(Input->ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_MASK || 
					Input->XonLimit < 0 || static_cast<ULONG>(Input->XonLimit) > DevExt->SerialQueueSize.InSize ||
					Input->XoffLimit < 0 || static_cast<ULONG>(Input->XoffLimit) > DevExt->SerialQueueSize.OutSize)
				{
					Status								= STATUS_INVALID_PARAMETER;
				}
				else
				{
					RtlCopyMemory(&DevExt->SerialHandFlow,SystemBuffer,sizeof(SERIAL_HANDFLOW));
				}
			}
		}
		break;

	case IOCTL_SERIAL_SET_LINE_CONTROL:
		{
			if(InputLength < sizeof(SERIAL_LINE_CONTROL))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				RtlCopyMemory(&DevExt->SerialLineControl,SystemBuffer,sizeof(SERIAL_LINE_CONTROL));
				Status									= Usb2ComSetLineControl(DevExt);
			}
		}
		break;

	case IOCTL_SERIAL_SET_MODEM_CONTROL:
		{
			if(InputLength < sizeof(ULONG))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				DevExt->SerialModemControl				= *static_cast<PUCHAR>(SystemBuffer);
				Status									= Usb2ComSetModemControl(DevExt);
			}
		}
		break;

	case IOCTL_SERIAL_SET_QUEUE_SIZE:
		{
			if(InputLength < sizeof(SERIAL_QUEUE_SIZE))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				RtlCopyMemory(&DevExt->SerialQueueSize,SystemBuffer,sizeof(SERIAL_QUEUE_SIZE));
			}
		}
		break;

	case IOCTL_SERIAL_SET_RTS:
		{
			Status										= Usb2ComSetRTS(DevExt);
		}
		break;

	case IOCTL_SERIAL_SET_TIMEOUTS:
		{
			if(InputLength < sizeof(SERIAL_TIMEOUTS))
			{
				Status									= STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				PSERIAL_TIMEOUTS Input					= static_cast<PSERIAL_TIMEOUTS>(SystemBuffer);

				if(Input->ReadIntervalTimeout == MAXULONG && Input->ReadTotalTimeoutConstant == MAXULONG && Input->ReadTotalTimeoutConstant == MAXULONG)
					Status								= STATUS_INVALID_PARAMETER;
				else
					RtlCopyMemory(&DevExt->SerialTimeouts,SystemBuffer,sizeof(SERIAL_TIMEOUTS));
			}
		}
		break;

	//case IOCTL_SERIAL_SET_WAIT_MASK:
	//	break;

	//case IOCTL_SERIAL_WAIT_ON_MASK:
	//	break;

	default:
		Status											= STATUS_INVALID_DEVICE_REQUEST;
		break;
	}

	if(Status != STATUS_PENDING)
	{
		Irp->IoStatus.Status							= Status;
		Irp->IoStatus.Information						= Information;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);
		IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
	}

	return Status;
}

//
// updater serial status
//
NTSTATUS Usb2ComUpdateSerialStatus(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
	DevExt->SerialStatus.AmountInInQueue				= DevExt->ReadBufferCharsCount;
	DevExt->SerialStatus.AmountInOutQueue				= DevExt->PendingWriteCharsCount;
	DevExt->SerialStatus.EofReceived					= FALSE;
	DevExt->SerialStatus.Errors							= 0;
	DevExt->SerialStatus.WaitForImmediate				= FALSE;
	DevExt->SerialStatus.HoldReasons					= 0;

	if(DevExt->TxHoldReason & SERIAL_TX_CTS)
		DevExt->SerialStatus.HoldReasons				|= SERIAL_TX_WAITING_FOR_CTS;

	if(DevExt->TxHoldReason & SERIAL_TX_DSR)
		DevExt->SerialStatus.HoldReasons				|= SERIAL_TX_WAITING_FOR_DSR;

	if(DevExt->TxHoldReason & SERIAL_TX_DCD)
		DevExt->SerialStatus.HoldReasons				|= SERIAL_TX_WAITING_FOR_DCD;

	if(DevExt->RxHoldReason & SERIAL_RX_DSR)
		DevExt->SerialStatus.HoldReasons				|= SERIAL_RX_WAITING_FOR_DSR;

	return STATUS_SUCCESS;
}

//
// process event
//
NTSTATUS Usb2ComProcessEvent(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in ULONG EventFlags)
{
	return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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