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

📄 serdev.cpp

📁 串口驱动程序
💻 CPP
字号:
// serdev.cpp - device class implementation for serial driver example
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060  USA
//
// Copyright (c) 1998 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================

#include <vdw.h>
#include "serdev.h"
#include "glbtrace.h"

// Class SerialDevice implements an abstract serial device that conforms
// to the NT serial interface. It is designed as a base class from which
// you can derive classes specific to a particular kind of hardware, most
// obviously a UART type device. 
//
// IRPs are managed as follows. 
// 1. IOCTLs are handled immediately, with the exception of 
//    IOCTL_SERIAL_WAIT_ON_MASK.
//
// 2. Reads are queued to data member m_ReadIrpQueue, an instance of
//	  SerialReadQueue, which is derived from KDriverManagedQueue.
//
// 3. Writes and flushes are queued to data member m_WriteIrpQueue, an
//    an instance of SerialWriteQueue, also derived from KDriverManagedQueue.
//
// 4. IOCTL_SERIAL_SET_WAIT_MASK and IOCTL_SERIAL_WAIT_ON_MASK are 
//    serialized through m_WaitIrpQueue, an instance of SerialWaitQueue.
//
// 5. Create, CleanUp, Close, SetFileInformation, and QueryFileInformation
//    are handled immediately.
//
// The base class takes care of most all the IRP processing, so derived
// classes do not use DEVMEMBER_DISPATCHERS. Instead, they declare
// overrides of the IRP handling member functions that require special
// treatment.
//
// See serrdwr.cpp for information on how subclasses implement read/write
// functionality, and serevent.cpp for information on how subclasses implement
// event generation.
//

/////////////////////////////////////////////////////////////////////////////
// Begin INIT code section
#pragma code_seg("INIT")

/////////////////////////////////////////////////////////////////////////////
// Constructor
//
SerialDevice::SerialDevice(
		PCWSTR DeviceName,
		PCWSTR LinkName,
		ULONG Characteristics,
		ULONG Flags
		) :

	KDevice(
		DeviceName,
		FILE_DEVICE_SERIAL_PORT,
		NULL,					// create unprotected link later
		Characteristics,
		Flags
		),

	m_ReadMutex(ULONG(0))
{
	GTRACE((TLEVEL,"Constructor for Serial Device\n"));

// Initialize the IRP queues
	m_ReadIrpQueue.SetDevice(this);
	m_WriteIrpQueue.SetDevice(this);
	m_WaitIrpQueue.SetDevice(this);

// Set up all DPCs
	m_ReadCompleteDpc.Setup(LinkTo(ReadComplete), this);
	m_WriteCompleteDpc.Setup(LinkTo(WriteComplete), this);
	m_EventDpc.Setup(LinkTo(EventDetected), this);
	m_StartReadTimerDpc.Setup(LinkTo(StartReadTimer), this);
	m_StartWriteTimerDpc.Setup(LinkTo(StartWriteTimer), this);

	if (LinkName)
	{
		if ( (m_Link = new (PagedPool) WCHAR[ustrlen(LinkName)+1]) != NULL )
		{
			m_ConstructorStatus = CreateLink(LinkName, FALSE); // unprotected link
			ustrcpy(m_Link, LinkName);
		}
		else
			m_ConstructorStatus = STATUS_INSUFFICIENT_RESOURCES;
	}
	else
		m_Link = NULL;

// Zero out miscellaneous data members
	m_WaitMask = 0;
#if NTVERSION > 351
	IoctlClearStatistics();
#endif
	RtlZeroMemory(&m_Timeouts, sizeof(SERIAL_TIMEOUTS));
	RtlZeroMemory(&m_Chars, sizeof(SERIAL_CHARS));
	RtlZeroMemory(&m_Handflow, sizeof(SERIAL_HANDFLOW));
	m_ReadBuffer = NULL;
	m_WriteBuffer = NULL;
	m_ReadCount = 0;
	m_WriteCount = 0;
	m_SupportedEvents = 0;
	m_EventState = 0;
	m_ErrorState = 0;
	m_DeviceMapName = NULL;
}

/////////////////////////////////////////////////////////////////////////////
// AddDeviceMapEntry
//
// This function writes the device map entry. It is the responsibility of
// the subclass to call this if it constructs successfully.
//
NTSTATUS SerialDevice::AddDeviceMapEntry(PCWSTR DeviceName, PCWSTR LinkName)
{
	m_DeviceMapName = new (PagedPool) WCHAR[ustrlen(DeviceName)+1];
	if ( !m_DeviceMapName )
		return STATUS_INSUFFICIENT_RESOURCES;

	ustrcpy(m_DeviceMapName, DeviceName);

	KRegistryKey DeviceMapKey(
		REGISTRY_DEVICEMAP,
		L"SERIALCOMM",
		TRUE,
		REG_OPTION_VOLATILE,
		KEY_DEFAULT_ACCESS | KEY_SET_VALUE
		);

	if ( NT_SUCCESS(DeviceMapKey.LastError()) )
		DeviceMapKey.WriteValue(DeviceName, LinkName);

	GTRACE((TLEVEL, "AddDeviceMapEntry status=%x\n", DeviceMapKey.LastError()));

	return DeviceMapKey.LastError();
}

#pragma code_seg()
// End INIT code section
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// Destructor
//
SerialDevice::~SerialDevice(void)
{
	GTRACE((TLEVEL,"Destructor for Serial Device\n"));

	if (m_Link)
		DestroyLink(m_Link);

	if (m_DeviceMapName != NULL)
	{
		KRegistryKey DeviceMapKey(
			REGISTRY_DEVICEMAP,
			L"SERIALCOMM",
			TRUE,
			REG_OPTION_VOLATILE,
			KEY_DEFAULT_ACCESS | KEY_SET_VALUE
			);

		DeviceMapKey.DeleteValue(m_DeviceMapName);

		delete m_DeviceMapName;
	}
}

/////////////////////////////////////////////////////////////////////////////
// Create
//
// This is an exclusive device.
//
NTSTATUS SerialDevice::Create(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::Create\n"));

#if NTVERSION > 351
	IoctlClearStatistics();
#endif

	return DefaultDispatch(I);
}

/////////////////////////////////////////////////////////////////////////////
// Close
//
NTSTATUS SerialDevice::Close(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::Close\n"));
	return DefaultDispatch(I);
}

/////////////////////////////////////////////////////////////////////////////
// Read
//
NTSTATUS SerialDevice::Read(KIrp I)
{
//	GTRACE((TLEVEL,"SerialDevice::Read\n"));

	NTSTATUS status;

	m_ReadMutex.Wait();

	status = m_ReadIrpQueue.MaybeQueueIrp(I);

	m_ReadMutex.Release();

	return status;
}

/////////////////////////////////////////////////////////////////////////////
// Write
//
NTSTATUS SerialDevice::Write(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::Write\n"));

	return m_WriteIrpQueue.QueueIrp(I);
}

/////////////////////////////////////////////////////////////////////////////
// CleanUp
//
NTSTATUS SerialDevice::CleanUp(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::CleanUp\n"));

	m_ReadIrpQueue.CleanUp(I.FileObject());
	m_WriteIrpQueue.CleanUp(I.FileObject());
	m_WaitIrpQueue.CleanUp(I.FileObject());

	CancelCurrentRead();
	CancelCurrentWrite();
	CancelCurrentEventWait();

	return DefaultDispatch(I);
}

/////////////////////////////////////////////////////////////////////////////
// SetInformation
//
NTSTATUS SerialDevice::SetInformation(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::SetInformation\n"));
	NTSTATUS status;

	I.Information() = 0;

	FILE_INFORMATION_CLASS fc = I.SetFileInformationClass();

	if ( (fc==FileEndOfFileInformation) || (fc==FileAllocationInformation) )
		status = STATUS_SUCCESS;
	else
		status = STATUS_INVALID_PARAMETER;

	return I.Complete(status);
}

/////////////////////////////////////////////////////////////////////////////
// QueryInformation
//
NTSTATUS SerialDevice::QueryInformation(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::QueryInformation\n"));

	FILE_INFORMATION_CLASS fc = I.QueryFileInformationClass();

	NTSTATUS status = STATUS_SUCCESS;

	switch (fc)
	{
	case FileStandardInformation:
	{
        PFILE_STANDARD_INFORMATION si = (PFILE_STANDARD_INFORMATION)I.BufferedReadDest();
		si->AllocationSize.QuadPart = 0;
		si->EndOfFile = si->AllocationSize;
		si->NumberOfLinks = 0;
		si->DeletePending = FALSE;
		si->Directory = FALSE;
		I.Information() = sizeof(FILE_STANDARD_INFORMATION);		
		break;
	}
	case FilePositionInformation:
	{
        PFILE_POSITION_INFORMATION pi = (PFILE_POSITION_INFORMATION)I.BufferedReadDest();
		pi->CurrentByteOffset.QuadPart = 0;
		I.Information() = sizeof(FILE_POSITION_INFORMATION);
		break;
	}
	default:
		I.Information() = 0;
		status = STATUS_INVALID_PARAMETER;
	}

	return I.Complete(status);
}

/////////////////////////////////////////////////////////////////////////////
// FlushBuffers
//
NTSTATUS SerialDevice::FlushBuffers(KIrp I)
{
	GTRACE((TLEVEL,"SerialDevice::FlushBuffers\n"));

// Flush goes to the write queue.

	return m_WriteIrpQueue.QueueIrp(I);
}

⌨️ 快捷键说明

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