📄 isotalker.cpp
字号:
/************************************************************************
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
* PURPOSE.
************************************************************************/
/************************************************************************
*
* Module: IsoTalker.cpp
* Long name: Isochronous Talker class implementation
* Description: Simple class which handles transmitting of data over an
* isochronous channel.
*
* Runtime Env.: Win32
* Author(s): Frank Senf
* Company: Thesycon GmbH, Ilmenau
************************************************************************/
#include "IsoTalker.h"
// constructor implementation
CIsoTalker::CIsoTalker()
{
// init members
m_BufferError = 0;
m_File = NULL;
m_Pattern = 0x00;
m_ThreadExited = false;
m_IsoFrameBytes = 0;
} // ctor
// destructor implementation
CIsoTalker::~CIsoTalker()
{
// ensure all resources are released
CloseFile();
} // dtor
// open the source file
unsigned long
CIsoTalker::OpenFile(const char* Filename)
{
unsigned long retval;
if ( m_File == NULL ) {
// open the file, file must exist
m_File = ::CreateFile(
Filename, // name of file
GENERIC_READ, // access mode
FILE_SHARE_READ,// share mode (0=not shared)
NULL, // security descriptor
OPEN_EXISTING, // how to create
0, // file flags and attributes
NULL // handle to template file
);
if ( m_File == INVALID_HANDLE_VALUE ) {
// opening input file failed
retval = ::GetLastError();
m_File = NULL;
} else {
// file successfully opened
retval = 0;
}
} else {
// an input file was already opened
retval = 1;
}
return retval;
} // OpenFile
// close the source file
void CIsoTalker::CloseFile()
{
if ( m_File!=NULL ) {
::CloseHandle(m_File);
m_File = NULL;
}
} // CloseFile
// overloaded CVhpdThread::TerminateThread() function
// NOTE 1: called in the context of the main thread
// NOTE 2: TerminateThread() is overloaded to ensure that the
// thread will exit. This is done by trying to terminate the
// thread until it really terminates. For future version of VHPDLib
// this will be implemented by the base class
void CIsoTalker::TerminateThread()
{
// cancel all pending notification buffers, this forces the worker thread
// to resume from a wait state and check for termination
AbortIoBuffers();
// now wait for the thread to terminate
if ( mThreadHandle != NULL ) {
// loop until thread has terminated
for (;;) {
// wait on thread handle, 40 ms timeout
DWORD err = WaitForSingleObject(mThreadHandle,40);
if ( err==WAIT_OBJECT_0 ) {
// handle is signaled, done
break;
}
if ( err==WAIT_TIMEOUT ) {
// wait timed out
// cancel all pending notification buffers again, should force the worker thread
// to resume from the wait state and check for termination
AbortIoBuffers();
// loop and wait again
continue;
}
// neither WAIT_OBJECT_0 nor WAIT_TIMEOUT returned -> error during wait
break;
} // for()
}
} // TerminateThread
// overloaded CVhpdThread::OnThreadExit() function
// NOTE: It is called in the context of the worker thread.
void CIsoTalker::OnThreadExit()
{
// store new thread state
m_ThreadExited = true;
} // OnThreadExit
// overloaded pre-process buffer function
// returns FALSE to stop data transfer, TRUE to continue
BOOL CIsoTalker::PreProcessBuffer(
CVhpdBuf* Buf,
VHPD_ISOCH_SUBMIT_BUFFER* Submit
)
{
if ( m_File == NULL ) {
// no input file, fill buffer with fixed pattern
memset(Buf->Buffer(),m_Pattern,Buf->Size());
// we submit the whole buffer
// NOTE: Buf->mNumberOfBytesToTransfer must be an integer product either
// of the mMaxBytesPerFrame base class member or
// of the Submit->BytesPerFrame member
Buf->mNumberOfBytesToTransfer = Buf->Size();
// no additional buffer options, we leave Submit structure untouched
return TRUE;
} else {
// read data from file
// first we check if we have stored some bytes from the last file read for transfer
if ( m_IsoFrameBytes != 0 ) {
// we have a copy of the last few bytes of the file, transfer it and stop transfer
memcpy(Buf->Buffer(),m_IsoFrame,m_IsoFrameBytes);
Buf->mNumberOfBytesToTransfer = m_IsoFrameBytes;
// adjust size of isochronous frame according to remaining data
Submit->BytesPerFrame = m_IsoFrameBytes;
// locally stored data is transferred
m_IsoFrameBytes = 0;
// transfer this buffer
return TRUE;
// next time the ReadFile call will file cause the end of file is reached
}
unsigned long Bytecount = 0;
if ( !(::ReadFile(m_File, Buf->Buffer(), Buf->Size(), &Bytecount, NULL)) ) {
// serious error while reading from file
// stop data transfer
return FALSE;
}
// ReadFile returns success (0) and sets number of bytes read to zero if the
// file pointer was beyond EOF
if ( Bytecount == 0 ) {
// end of file reached, stop data transfer
return FALSE;
}
if ( Bytecount != Buf->Size() ) {
// buffer only partly filled with the last bytes of the file
// we transfer a multiple of mMaxBytesPerFrame with this buffer and
// store the last few bytes locally for transferring it with the next buffer
unsigned long bufferfill = (Bytecount/mMaxBytesPerFrame) * mMaxBytesPerFrame;
if ( bufferfill == 0 ) {
// not enough bytes for an full-sized isochronous frame
Buf->mNumberOfBytesToTransfer = Bytecount;
// adjust size of isochronous frame according to remaining data
Submit->BytesPerFrame = Bytecount;
// submit this buffer
return TRUE;
} else {
// we transfer a multiple of mMaxBytesPerFrame with this buffer and
// store the last few bytes locally for transferring it with the next buffer
Buf->mNumberOfBytesToTransfer = bufferfill;
// no additional buffer options, we leave Submit structure untouched
memcpy(m_IsoFrame,((unsigned char*)(Buf->Buffer())+bufferfill),(Bytecount-bufferfill));
m_IsoFrameBytes = (Bytecount-bufferfill);
// submit this buffer
return TRUE;
}
} else {
// buffer completely filled
Buf->mNumberOfBytesToTransfer = Buf->Size();
// no additional buffer options, we leave Submit structure untouched
return TRUE;
}
}
} // PreProcessBuffer
// function is called after a buffer is completed by the driver
void
CIsoTalker::PostProcessBuffer(
CVhpdBuf* Buf,
VHPD_ISOCH_SUBMIT_BUFFER* Submit)
{
if ( Buf->mStatus == VHPD_STATUS_SUCCESS ) {
// completed with success
} else {
// completed with error, just count and store it
m_BufferError++;
m_LastError = Buf->mStatus;
}
return;
} // PostProcessBuffer
/*************************** EOF **************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -