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

📄 ezusbisotransfer.h

📁 DriverStdio的一个USB驱动程序
💻 H
📖 第 1 页 / 共 2 页
字号:
	if( (USB_STREAM_STATUS_CONTINUE == StreamStatus) && !StopRequested() )
	{
// handle stream continuation
		I.Reuse();

		m_pDev->SubmitUrb(I, pUrb, IsoTransferComplete, pContext);
		return STATUS_MORE_PROCESSING_REQUIRED;
	}

// The stream has been stopped (This URB was not re-submitted)
	if(! --m_PendingIrpCount)
	{
		//for synchronous starts, set event that StartStream is waiting on
		m_pIsoXferDoneEvent->Set();
		
		//for asynchronous starts, call client callback routine
		if( pContext->m_pfnClientCallback )
		{
			pContext->m_pfnClientCallback(
				pContext->m_pClientContext
				);
		}

		delete m_pContext;
		m_bStarted = FALSE;
	}

	return STATUS_MORE_PROCESSING_REQUIRED;
}

template <class T>
NTSTATUS KUsbIsochStream<T>::WaitForTransferToFinish(ULONG mSecTimeOut)  
{ 
	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );

	ULONGLONG TimeOut100nSec;
	PLARGE_INTEGER pTimeOut;
	NTSTATUS status = STATUS_SUCCESS;

	if( 0 != mSecTimeOut )
	{
		// it's positive, and then convert to negative afterwards.
		LONG mSecTimeOutSigned = LONG(mSecTimeOut);
		
		if(mSecTimeOutSigned < 0) 
		{
			mSecTimeOutSigned = -mSecTimeOutSigned;
		}

		mSecTimeOut = ULONG(mSecTimeOutSigned);

		// Calculate wait as 100ns intervals.  Negative is relative
		TimeOut100nSec = mSecTimeOut;
		TimeOut100nSec *= -10000;	// convert units
		pTimeOut = PLARGE_INTEGER(&TimeOut100nSec);		
	}			
	else
	{
		pTimeOut = NULL;
	}

	status = m_pIsoXferDoneEvent->Wait(KernelMode, FALSE, pTimeOut, Executive); 

	return status;
}



//=============================================================================
// class EzUsbIsoTransferBase
//
// This class is a base class for EzUsbIsoTransfer and EzUsbDriverManagedIsoTransfer.
// 
class EzUsbIsoTransferBase
{
//Construction/Destruction
protected:
	EzUsbIsoTransferBase(
		KUsbPipe& pipe,
		USHORT PacketSize=0,
		UCHAR PacketsPerUrb=0,
		UCHAR NumUrbs=2
		);

	SAFE_DESTRUCTORS

	~EzUsbIsoTransferBase(void);

private:
	EzUsbIsoTransferBase(void);
	EzUsbIsoTransferBase(EzUsbIsoTransferBase&);
	EzUsbIsoTransferBase& operator=(EzUsbIsoTransferBase&);

//Methods
public:
	PURB GetUrb(UCHAR index);
	UCHAR NumberOfUrbs(void)	{return m_NumUrbs;}
	NTSTATUS Status(void)		{return m_ConstructorStatus;}
	ULONG TotalPackets(void)	{return m_dwTotalPacketsProcessed;}
	ULONG TotalBytes(void)		{return m_dwTotalBytesProcessed;}
	ULONG ErrorPackets(void)	{return m_dwErrorPacketCount;}

//Data Members
protected:
	KUsbPipe& m_Pipe;
	//pointer to an array of PMDLs
	MDL** m_ppMdl;	 
	//pointer to an array of PURBs
	PVOID m_pUrb;	 
	//size in bytes of an URB
	ULONG m_UrbSize; 
	//number of packets per URB
	UCHAR m_PacketsPerUrb;
	//size of data payload in one packet
	USHORT m_PacketSize;
	//Direction of transfer TRUE if its an IN(read from device), FALSE if its an OUT(write to device)
	bool m_bRead;
	NTSTATUS m_ConstructorStatus;
	//Number of URBs to use for transfers
	UCHAR m_NumUrbs;
	//Size of the TransferBuffer
	ULONG m_TransferSize;
	//total number of packets processed
	ULONG m_dwTotalPacketsProcessed;
	//total number of successful bytes processed
	ULONG m_dwTotalBytesProcessed;
	//total number of packets with bad status
	ULONG m_dwErrorPacketCount;
};

inline PURB EzUsbIsoTransferBase::GetUrb(UCHAR index)
{
	return reinterpret_cast<PURB>(reinterpret_cast<PUCHAR>(m_pUrb) + m_UrbSize * index);
}



//=============================================================================
// class EzUsbIsoTransfer
//
// This class abstracts an isochronous transfer.  It can be used for reads 
// and writes.  The class accepts a KMemory object that models a locked buffer
// to use in the transfer.  The class will segment the buffer into URB's.  
// After constructing an instance with a valid KMemory object with a resident
// locked buffer, drivers call method Start to begin isochronous transfers.
// The tranfer will be stopped on failure or by calling method Stop.
// 
class EzUsbIsoTransfer : public EzUsbIsoTransferBase
{
//Construction/Destruction
public:
	EzUsbIsoTransfer(
		KMemory& Mdl,			//Data Buffer
		ULONG Length,			//Size of Data Buffer in bytes
		KUsbPipe& pipe,			//Pipe to perform the isochronous transfer
		USHORT PacketSize=0,	//Iso Packet Size to use in the transfer (default is max for the pipe)
		UCHAR PacketsPerUrb=0,	//Number of packets per urb (max of 255)
		PVOID pDescBuffer=NULL,	//Optional pointer to packet buffer
		UCHAR NumUrbs=2			//Number of queued transfers at a time
		);

	SAFE_DESTRUCTORS;

	~EzUsbIsoTransfer(void);

private:
	EzUsbIsoTransfer(void);
	EzUsbIsoTransfer(EzUsbIsoTransfer&);
	EzUsbIsoTransfer& operator=(EzUsbIsoTransfer&);

//Methods
public:
	//Initiate continuous isoch xfers (asynchronous form)
	NTSTATUS Start(
		PISO_TRANSFER_COMPLETE_CALLBACK pfnCallback, //Callback when operation is complete
		PVOID pClientContext=NULL					 //context for callback
		);
	//Initiate continuous isoch xfers (synchronous form)
	NTSTATUS Start(ULONG mSecTimeOut=0);
	//stop isoch xfers   
	NTSTATUS Stop(
		BOOLEAN bWait = TRUE, 
		ULONG mSecTimeOut = 100
		);
	//This Method is called by KUsbIsochStream<EzUsbIsoTransfer> 
	USB_STREAM_STATUS OnCompletedUrb(PURB pUrb, NTSTATUS status);

//Data members
protected:

	//Client buffer
	KMemory m_Mem;
	//Buffer base address
	PVOID m_VirtualAddress;
	//Offset into buffer
	ULONG m_dwOffset;
	//Length of user supplied buffer
	ULONG m_Length;
	//Optional pointer to a buffer to hold USBD_ISO_PACKET_DESCRIPTOR's (client provides storage)
    PVOID m_pDescriptorBuffer;
	//Offset into descriptor buffer
	ULONG m_dwDescrOffset;
	//This object abstracts IRP processing
	KUsbIsochStream<EzUsbIsoTransfer> stream;
};


inline NTSTATUS EzUsbIsoTransfer::Start(
	PISO_TRANSFER_COMPLETE_CALLBACK pfnCallback,
	PVOID pClientContext
	)
{
	return stream.StartStream(pfnCallback,pClientContext);
}


inline NTSTATUS EzUsbIsoTransfer::Start(ULONG mSecTimeOut)
{
	return stream.StartStream(mSecTimeOut);
}


inline NTSTATUS EzUsbIsoTransfer::Stop(
	BOOLEAN bWait, 
	ULONG mSecTimeOut
	)
{
	return stream.StopStream(bWait,mSecTimeOut);
}



//=============================================================================
// class EzUsbDriverManagedIsoTransfer
//
// This class abstracts isochronous transfers.  The class provides a buffer for
// performing Isochronous reads from a USB device.  After constructing an 
// instance, drivers call method Start to begin continuous isochronous transfers
// from the USB device.  Drivers call method ReadBuffer to obtain data from 
// the buffer. Iso Packet Descriptors are optionally saved by the object.  
// Method ReadDescriptors can be used to obtain them.  The continuous tranfers
// will be stopped on failure or by calling method Stop.
//
class EzUsbDriverManagedIsoTransfer : public EzUsbIsoTransferBase, protected KLockableFifo<UCHAR>
{
//Construction/Destruction
public:
	EzUsbDriverManagedIsoTransfer(
		KUsbPipe& pipe,		//Pipe to perform iso transfers
		ULONG Length,		//Size of Data Buffer in bytes
		USHORT PacketSize,  //Size of packet to use
		UCHAR PacketsPerUrb,//Number of packets per URB (max 255)
		UCHAR NumUrbs=2,	//Number of queued URB's at a time
		ULONG NumPackets=0,	//Optional Number of Packets to save in a buffer
		PVOID pBuffer=NULL	//Optional pointer to a data buffer
		);

	SAFE_DESTRUCTORS
	~EzUsbDriverManagedIsoTransfer(void);

private:
	EzUsbDriverManagedIsoTransfer(void);
	EzUsbDriverManagedIsoTransfer(EzUsbDriverManagedIsoTransfer&);
	EzUsbDriverManagedIsoTransfer& operator=(EzUsbDriverManagedIsoTransfer&);

//Methods 
public:
	//clients use this copy data from the data buffer
	ULONG ReadBuffer(PVOID ptr, ULONG len);

	//clients use this to copy USBD_ISO_PACKET_DESCRIPTORS from the buffer 
	ULONG ReadDescriptorBuffer(PVOID pBuff, ULONG dwNumDescriptorsToRead);

	//Initiate continuous isoch xfers (asynchronous form)
	NTSTATUS Start(
		PISO_TRANSFER_COMPLETE_CALLBACK pfnCallback,
		PVOID pClientContext=NULL
		);

	//Initiate continuous isoch xfers (synchronous form)
	NTSTATUS Start(ULONG mSecTimeOut=0);

	//stop isoch xfers 
	NTSTATUS Stop(
		BOOLEAN bWait = TRUE, 
		ULONG mSecTimeOut = 100
		);

	BOOLEAN IsStarted(void){ return stream.IsStarted(); }

	//This method is called by KUsbIsochStream<EzUsbDriverManagedIsoTransfer> 
	USB_STREAM_STATUS OnCompletedUrb(PURB pUrb, NTSTATUS status);

protected:

	ULONG WriteBuffer(PURB);

	ULONG WriteDescriptorBuffer(PUSBD_ISO_PACKET_DESCRIPTOR ptr, ULONG dwNumDescriptorsToPutInBuffer);

//Data members
protected:
	//Optional USBD_ISO_PACKET_DESCRIPTOR buffer
    KLockableFifo<USBD_ISO_PACKET_DESCRIPTOR>* m_pDescriptorBuffer;
	//Temporary buffers
	PVOID m_TransferBuffers;
	//Object that manages the recycling IRPs to perform the transfer
	KUsbIsochStream<EzUsbDriverManagedIsoTransfer> stream;
};


inline NTSTATUS EzUsbDriverManagedIsoTransfer::Start(
	PISO_TRANSFER_COMPLETE_CALLBACK pfnCallback,
	PVOID pClientContext
	)
{
	return stream.StartStream(pfnCallback,pClientContext);
}


inline NTSTATUS EzUsbDriverManagedIsoTransfer::Start(ULONG mSecTimeOut)
{
	return stream.StartStream(mSecTimeOut);
}


inline NTSTATUS EzUsbDriverManagedIsoTransfer::Stop(
	BOOLEAN bWait, 
	ULONG mSecTimeOut
	)
{
	return stream.StopStream(bWait,mSecTimeOut);
}

#endif // #ifndef __EzUsbIsoTransfer__h__

⌨️ 快捷键说明

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