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

📄 serrdwr.cpp

📁 串口驱动程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Handle read interval timeout
//
VOID SerialDevice::ReadIntervalExpired(PVOID arg1, PVOID arg2)
{
	if (SynchronizeReceiverAccess(LinkTo(SynchReadIntervalExpired), this))
	{
		LARGE_INTEGER Large; 
		Large.QuadPart = m_IntervalTimerPeriod;
		m_ReadIntervalCallback.Set(
			Large,
			LinkTo(ReadIntervalExpired),
			this
			);
	}
}

/////////////////////////////////////////////////////////////////////////////
// SynchReadIntervalExpired
//
// Synchronized handling of interval timer
//
BOOLEAN SerialDevice::SynchReadIntervalExpired(void)
{
// if the read is done, there is nothing to do

	if (m_ReadCount == 0)
		return FALSE;

	LARGE_INTEGER Now;
	KeQuerySystemTime(&Now);

// if no characters have arrived since the last call, then check the
// elapsed time

	if ( (m_ReadCount == m_ReadCountLastInterval) && (m_ReadCount != 0) )
	{
		LONGLONG Elapsed = Now.QuadPart - m_TimeLastInterval;
		if (Elapsed > m_MaxCharacterInterval)
		{
			m_ReadCompleteDpc.Request((PVOID)STATUS_TIMEOUT, (PVOID)m_ReadCount);
			m_ReadCount = 0;
			m_ReadBuffer = 0;
			m_ReadCountLastInterval = 0;
			return FALSE;
		}
	}

	m_ReadCountLastInterval = m_ReadCount;
	m_TimeLastInterval = Now.QuadPart;

	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// Static linkage members
//
// These static members pass control between SynchronizeReceiverAccess
// and various non-static members.
//
BOOLEAN SerialDevice::LinkTo(SynchCancelRead)(PVOID Context)
{
	return ((SerialDevice*)Context)->SynchCancelRead();
}

BOOLEAN SerialDevice::LinkTo(SynchReadIntervalExpired)(PVOID Context)
{
	return ((SerialDevice*)Context)->SynchReadIntervalExpired();
}

BOOLEAN SerialDevice::LinkTo(SynchReadStart)(PVOID Context)
{
	_read_start* prs = (_read_start*)Context;

	return prs->device->SynchReadStart(prs->buffer, prs->count);
}

/////////////////////////////////////////////////////////////////////////////
// Synchronize access to receiver data
//
// Most subclasses will override this member function. The function is 
// designed to be compatible with subclasses that need interrupt level
// synchronization, although a subclass could equally well implement
// this function by acquiring a spin lock, making the call, and releasing
// the spin lock. The base class just calls the function.

BOOLEAN SerialDevice::SynchronizeReceiverAccess(
		PKSYNCHRONIZE_ROUTINE func,
		PVOID context
		)
{
	return func(context);
}

/////////////////////////////////////////////////////////////////////////////
// CopyReceivedData
//
// Copy any unsolicited data which has been buffered while no read was
// pending. The base class has none. Most subclasses will override
// this member.
//
ULONG SerialDevice::CopyReceivedData(PUCHAR buffer, ULONG count)
{
	return 0;
}


struct CopyReceivedDataArgs
{
	SerialDevice* device;
	PUCHAR buf;
	ULONG count;
};


/////////////////////////////////////////////////////////////////////////////
// NoPendRead
//
// Non-blocking read for special RAS support
//
NTSTATUS SerialDevice::NoPendRead(KIrp I)
{
	CopyReceivedDataArgs crsargs;
	crsargs.device = this;
	crsargs.buf = (PUCHAR)I.BufferedReadDest();
	crsargs.count = I.ReadSize();

	SynchronizeReceiverAccess(LinkTo(CopyReceivedData), &crsargs);

	if ( ((m_Timeouts.ReadIntervalTimeout == MAXULONG) &&
	      (m_Timeouts.ReadTotalTimeoutMultiplier == 0) &&
	      (m_Timeouts.ReadTotalTimeoutConstant == 0) 
		 ) || (crsargs.count > 0)
	   )
	{
		I.Information() = crsargs.count;
		I.Complete(STATUS_SUCCESS);
		return STATUS_SUCCESS;
	}
	else 
		return STATUS_MORE_PROCESSING_REQUIRED;
}

///////////////// Functions for Write //////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// CancelCurrentWrite
//
// Cancel the current write operation
//
VOID SerialDevice::CancelCurrentWrite(void)
{
	SynchronizeTransmitterAccess(LinkTo(SynchCancelWrite), this);
}

/////////////////////////////////////////////////////////////////////////////
// SynchCancelWrite
//
// Cancel the current write operation
//
BOOLEAN SerialDevice::SynchCancelWrite(void)
{
	BOOLEAN status = (m_WriteBuffer != 0);

	m_FinalWriteCount = m_WriteCount;
	m_WriteBuffer = 0;
	m_WriteCount = 0;

	return status;
}

/////////////////////////////////////////////////////////////////////////////
// Start a write operation
//
// Subclasses should override this member if additional functionality
// is required, as will most often be the case. 
//
VOID SerialDevice::StartWrite(PUCHAR buffer, ULONG count)
{
	ASSERT (m_WriteBuffer == NULL);

// Handle a write of zero characters

	if (count == 0)
	{
		m_WriteIrpQueue.CompleteCurrent(STATUS_SUCCESS, 0);
		return;
	}

	GTRACE( (TLEVEL, "Start write: |%s|\n", buffer));


// Set up write state data

	m_WriteBuffer = buffer;
	m_WriteCount = count;

// If the write has a timeout, start it

	if (m_Timeouts.WriteTotalTimeoutMultiplier ||
	    m_Timeouts.WriteTotalTimeoutConstant )

		m_StartWriteTimerDpc.Request((PVOID)count);
}

/////////////////////////////////////////////////////////////////////////////
// WriteComplete
//
// Finish a write operation (this is a DPC). Status is arg1.
// The subclass must request DPC m_WriteCompleteDpc when it
// detects that a write is complete. The constructor for
// SerialDevice sets up the DPC to call this function.
//
VOID SerialDevice::WriteComplete(PVOID arg1, PVOID arg2)
{
	NTSTATUS status = (NTSTATUS)arg1;

// Cancel a write timeout if one is active	

	if ((status != STATUS_TIMEOUT) && (m_WriteTimeout != 0))
	{
		m_WriteTimeout = 0;
		m_WriteExpiredCallback.Cancel();
	}

	m_WriteIrpQueue.CompleteCurrent(status, m_FinalWriteCount);
}

/////////////////////////////////////////////////////////////////////////////
// StartWriteTimer
//
// Start timing a write. This is a DPC. arg1 is the character count.
//
VOID SerialDevice::StartWriteTimer(PVOID arg1, PVOID arg2)
{
	LONGLONG Count = (LONGLONG)(LONG)arg1;
	LARGE_INTEGER l;

	m_WriteTimeout =
		m_Timeouts.WriteTotalTimeoutConstant + 
		(Count*m_Timeouts.WriteTotalTimeoutMultiplier);

	l.QuadPart = 10000 * (ULONGLONG)(-m_WriteTimeout);

	m_WriteExpiredCallback.Set(l, LinkTo(WriteExpired), this);
}

/////////////////////////////////////////////////////////////////////////////
// WriteExpired
//
// Handle Write timeout
//
VOID SerialDevice::WriteExpired(PVOID arg1, PVOID arg2)
{
	if (SynchronizeTransmitterAccess(LinkTo(SynchCancelWrite), this))
		WriteComplete( (PVOID)STATUS_TIMEOUT, NULL );
}

/////////////////////////////////////////////////////////////////////////////
// Synchronize transmitter access
//
// Most subclasses will override this member function. The function is 
// designed to be compatible with subclasses that need interrupt level
// synchronization, although a subclass could equally well implement
// this function by acquiring a spin lock, making the call, and releasing
// the spin lock. The base class just calls the function.

BOOLEAN SerialDevice::SynchronizeTransmitterAccess(
		PKSYNCHRONIZE_ROUTINE func,
		PVOID context
		)
{
	return func(context);
}

/////////////////////////////////////////////////////////////////////////////
// Static linkage members
//
// These static members pass control between SynchronizeReceiverAccess
// and various non-static members.
//
BOOLEAN SerialDevice::LinkTo(SynchCancelWrite)(PVOID Context)
{
	return ((SerialDevice*)Context)->SynchCancelWrite();
}

BOOLEAN SerialDevice::LinkTo(CopyReceivedData)(PVOID Context)
{
	CopyReceivedDataArgs* pcrs = (CopyReceivedDataArgs*)Context;
	
	pcrs->count = pcrs->device->CopyReceivedData(pcrs->buf, pcrs->count);

	return TRUE;
}


⌨️ 快捷键说明

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