📄 ezusbisotransfer.h
字号:
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 + -