📄 bcamadapter.cpp
字号:
);
if( ! s_hDevInterfaceNotify )
{
DWORD Err = GetLastError();
throw BcamException( BCAM_E_REGISTER_DEVICE_NOTIFICATION_FAILED, "CBcamAdapter::RegisterClient()", &Err );
}
}
*/
//------------------------------------------------------------------------------
/**
* \brief The client is unregistered.
*/
//------------------------------------------------------------------------------
/*void CBcamAdapter::UnregisterClient()
{
if (s_hDevInterfaceNotify != INVALID_HANDLE_VALUE)
{
::UnregisterDeviceNotification(s_hDevInterfaceNotify);
s_hDevInterfaceNotify = INVALID_HANDLE_VALUE;
s_hWndInterfaceNotify = NULL;
}
}
*/
//------------------------------------------------------------------------------
/**
* \brief The bus reset thread procedure.
* \param pv Pointer to a CResetContext containing shared information.
* Continuously requests a bus reset notification. If a notification is received
* the user provided callback function is called. If a stop is signalled the
* pending request is cancelled and the thread terminates.
*/
//------------------------------------------------------------------------------
DWORD WINAPI CBcamAdapter::BusResetThread( PVOID pv )
{
CResetContext *This = (CResetContext*) pv;
DWORD dwRet = 0;
This->m_ResetThreadRunning = true;
while (1)
{
DWORD numBytes;
ResetEvent( This->m_Overlapped.hEvent );
BOOL ret = ::DeviceIoControl(
This->m_hDevice,
IOCTL_BACC_GET_BUS_RESET_NOTIFICATION,
NULL, 0,
NULL, 0,
&numBytes,
&This->m_Overlapped );
DWORD dwRet = GetLastError();
if (ret || dwRet == ERROR_IO_PENDING)
{
ret = ::GetOverlappedResult( This->m_hDevice, &This->m_Overlapped, &numBytes, TRUE );
if (This->m_ResetThreadStop)
{
::CancelIo( This->m_hDevice );
break;
}
else
{
This->m_pResetCallback( *This->m_pAdapter, This->m_pResetContext );
}
}
else
{
break;
}
}
This->m_ResetThreadRunning = false;
ExitThread( dwRet );
#if MSC_VER < 1300
return dwRet;
#endif
}
//------------------------------------------------------------------------------
/**
* \brief Clears the bus reset context and stops the thread.
*
* Signals the bus reset thread to stop, awakes it by set the overlapped event
* and waits until it terminates. Then the resources are disposed.
*/
//------------------------------------------------------------------------------
void CBcamAdapter::ClearBusResetContext()
{
if (m_pResetContext)
{
// Stop thread
if( m_pResetContext->m_ResetThreadRunning )
{
m_pResetContext->m_ResetThreadStop = true;
do {
::SetEvent( m_pResetContext->m_Overlapped.hEvent );
} while (::WaitForSingleObject( m_pResetContext->m_hResetThread, 1000 ) == WAIT_TIMEOUT );
}
::CloseHandle( m_pResetContext->m_hDevice );
::CloseHandle( m_pResetContext->m_Overlapped.hEvent );
::CloseHandle( m_pResetContext->m_hResetThread );
delete m_pResetContext;
m_pResetContext = NULL;
}
}
//------------------------------------------------------------------------------
/**
* \brief A client callback function is registered and a thread is started.
*
* \throws BcamException if lacking resources.
*/
//------------------------------------------------------------------------------
void CBcamAdapter::SetOnBusResetCallback( BcamCallbackFunc pfunc, void* pv )
{
ClearBusResetContext();
if (pfunc != NULL)
{
unsigned long threadId;
m_pResetContext = new CResetContext();
ZeroMemory( m_pResetContext, sizeof *m_pResetContext );
m_pResetContext->m_ResetThreadStop = false;
m_pResetContext->m_ResetThreadRunning = false;
m_pResetContext->m_pResetCallback = pfunc;
m_pResetContext->m_pResetContext = pv;
m_pResetContext->m_pAdapter = this;
m_pResetContext->m_hDevice = CBcamDevCreator::OpenDevice( FullDeviceName( m_DeviceName ), TRUE );
m_pResetContext->m_Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if (m_pResetContext->m_Overlapped.hEvent == INVALID_HANDLE_VALUE)
throw BcamException( ::GetLastError(), _T( "CBcamAdapter::SetOnBusResetCallback" ) );
m_pResetContext->m_hResetThread = ::CreateThread( NULL, 0, BusResetThread, m_pResetContext, 0, &threadId );
if (! m_pResetContext->m_hResetThread)
throw BcamException( ::GetLastError(), _T( "CBcamAdapter::SetOnBusResetCallback" ) );
if (! ::SetThreadPriority( m_pResetContext->m_hResetThread, THREAD_PRIORITY_ABOVE_NORMAL ))
throw BcamException( ::GetLastError(), _T( "CBcamAdapter::SetOnBusResetCallback" ) );
// wait for the thread to run
DWORD ret;
do {
ret = ::WaitForSingleObject( m_pResetContext->m_hResetThread, 100 );
} while (WAIT_TIMEOUT == ret && ! m_pResetContext->m_ResetThreadRunning);
if (WAIT_FAILED == ret)
throw BcamException( ::GetLastError(), _T( "CBcamAdapter::SetOnBusResetCallback" ) );
}
}
//------------------------------------------------------------------------------
// list<CString> CBcamAdapter::DeviceNames()
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Creates a list of bacc devices
*
* \return
*
* Returns a list of device names
*/
//------------------------------------------------------------------------------
list<CString> CBcamAdapter::DeviceNames()
{
// create an empty list
list<CString> deviceNames;
// fill the list
DeviceNames( deviceNames );
// return a copy of the list
return deviceNames;
}
list<CString>& CBcamAdapter::DeviceNames(list<CString>& deviceNames)
{
const GUID classguid = GUID_BACC_DEVICE;
CBcamDevInfo hDevInfo( classguid );
DWORD i=0;
DWORD res = ERROR_SUCCESS;
do
{
SP_DEVICE_INTERFACE_DATA DevInterfaceData;
DevInterfaceData.cbSize = sizeof DevInterfaceData;
#if _SETUPAPI_VER >= 0x0500
if (::SetupDiEnumDeviceInterfaces( hDevInfo, NULL, &classguid, i, &DevInterfaceData ))
#else
if (::SetupDiEnumDeviceInterfaces( hDevInfo, NULL, const_cast<GUID*>( &classguid ), i, &DevInterfaceData ))
#endif
{
DWORD reqSize;
::SetupDiGetDeviceInterfaceDetail( hDevInfo, &DevInterfaceData, NULL, 0, &reqSize, NULL );
if (ERROR_INSUFFICIENT_BUFFER != (res = ::GetLastError()) )
throw BcamException( res, _T( "CBcamADapter::DeviceNames" ) );
char * const pBuffer = (char*) ::_alloca( reqSize );
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) pBuffer;
pDetail->cbSize = sizeof *pDetail;
if (::SetupDiGetDeviceInterfaceDetail( hDevInfo, &DevInterfaceData, pDetail, reqSize, &reqSize, NULL ))
{
deviceNames.push_back( FriendlyDeviceName( pDetail->DevicePath ) );
i++;
}
}
} while (res = GetLastError(), res == ERROR_SUCCESS);
if (res != ERROR_NO_MORE_ITEMS )
throw BcamException( res, _T( "CBcamAdapter::DeviceNames" ) );
return deviceNames;
}
//------------------------------------------------------------------------------
// void CBcamAdapter::Open( CString DeviceName, HWND hWndNotify )
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Opens a device and registers a client window.
*
* \param DeviceName String containing the device name.
*/
//------------------------------------------------------------------------------
void CBcamAdapter::Open( CString DeviceName )
{
TRACE( _T( "CBcamAdapter::Open(%s)\n" ), (LPCTSTR) DeviceName );
CString friendlyDeviceName = FriendlyDeviceName( DeviceName );
CString fullDeviceName = FullDeviceName( DeviceName );
if (IsOpen())
{
Close();
}
m_hDevice = CBcamDevCreator::OpenDevice( (LPCTSTR) fullDeviceName, true );
m_DeviceName = friendlyDeviceName;
TRACE( _T( "CBcamAdapter Handle = 0x%X\n" ), m_hDevice );
}
//------------------------------------------------------------------------------
// void CBcamAdapter::Close()
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Closes the device.
*/
//------------------------------------------------------------------------------
void CBcamAdapter::Close()
{
TRACE( _T("CBcamAdapter::Close() Handle = 0x%X\n" ), m_hDevice );
CloseHandle( m_hDevice );
m_hDevice = INVALID_HANDLE_VALUE;
}
//------------------------------------------------------------------------------
// bool CBcamAdapter::IsOpen()
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Checks the device handle.
*
* \return
*
* Returns true if device handle value is valid.
*/
//------------------------------------------------------------------------------
bool CBcamAdapter::IsOpen()
{
return m_hDevice != INVALID_HANDLE_VALUE;
}
//------------------------------------------------------------------------------
// void CBcamAdapter::ResetBus()
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Initiate a bus reset.
*
* \throws BcamException in case of failure.
*/
//------------------------------------------------------------------------------
void CBcamAdapter::ResetBus()
{
TRACE( _T( "CBcamAdapter::ResetBus()" ) );
BOOL ret;
ULONG numBytes;
BcamAdapterOL *pOl = GetNewBcamAdapterOL();
ret = DeviceIoControl( m_hDevice,
IOCTL_BACC_FIRE_BUS_RESET,
NULL, 0,
NULL, 0,
&numBytes,
&pOl->ol
);
if (FailedDevIO( ret ) && ::GetLastError() != ERROR_IO_PENDING)
{
delete pOl;
throw BcamException( ::GetLastError() );
}
ret = ::GetOverlappedResult( m_hDevice, &pOl->ol, &numBytes, true );
delete pOl;
if (FailedDevIO( ret ))
throw BcamException( ::GetLastError() );
}
//------------------------------------------------------------------------------
// ULONG CBcamAdapter::ResourcesAvailable( ULONG Speed )
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Retrieve how many bus resources are available.
*
* \param Speed At which transfer rate
* \return
*
* Number of bytes per packet
*
*/
//------------------------------------------------------------------------------
ULONG CBcamAdapter::ResourcesAvailable( TransferRate Speed )
{
TRACE( _T( "CBcamAdapter::ResourcesAvailable()" ) );
BOOL ret;
ULONG numBytes;
BaccArgGetResources arg;
BaccResGetResources res;
switch (Speed)
{
case TR_800:
arg.Speed = SPEED_FLAGS_800;
break;
case TR_400:
arg.Speed = SPEED_FLAGS_400;
break;
case TR_200:
arg.Speed = SPEED_FLAGS_200;
break;
case TR_100:
arg.Speed = SPEED_FLAGS_100;
break;
default:
throw BcamException( BCAM_E_INVALID_TRANSMISSION_RATE );
}
BcamAdapterOL *pOl = GetNewBcamAdapterOL();
ret = DeviceIoControl( m_hDevice,
IOCTL_BACC_GET_RESOURCES,
&arg, sizeof arg,
&res, sizeof res,
&numBytes,
&pOl->ol // NULL
);
if (ret == ERROR_IO_PENDING)
ret = GetOverlappedResult( m_hDevice, &pOl->ol, &numBytes, true );
delete pOl;
if (FailedDevIO( ret ) || numBytes < sizeof res)
throw BcamException( ::GetLastError() );
return res.BytesPerFrame;
}
//------------------------------------------------------------------------------
// ULONG CBcamAdapter::NumChannelAvailable()
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Retrieve how many isochronous channels are available.
*
* \return
*
* The number of isochronous channels available.
* \throws BcamException in case of failure
*/
//------------------------------------------------------------------------------
ULONG CBcamAdapter::NumChannelAvailable( ISOCHANNELSET &s )
{
TRACE( _T( "CBcamAdapter::NumChannelAvailable()" ) );
BOOL ret;
ULONG numBytes;
BaccArgGetResources arg;
BaccResGetResources res;
arg.Speed = SPEED_FLAGS_100; // doesn't matter but is required
BcamAdapterOL *pOl = GetNewBcamAdapterOL();
ret = DeviceIoControl( m_hDevice,
IOCTL_BACC_GET_RESOURCES,
&arg, sizeof arg,
&res, sizeof res,
&numBytes,
&pOl->ol // NULL
);
if (ret == ERROR_IO_PENDING)
ret = GetOverlappedResult( m_hDevice, &pOl->ol, &numBytes, true );
delete pOl;
if (FailedDevIO( ret ) || numBytes < sizeof res)
throw BcamException( ::GetLastError() );
for ( int c=0;res.ChSet.QuadPart!=0; res.ChSet.QuadPart>>=1, c++)
s[c] = res.ChSet.QuadPart&1;
return res.Channels;
}
//------------------------------------------------------------------------------
// ULONG CBcamAdapter::ReadQuad( ULONG Id, LARGE_INTEGER Adr )
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Reads a quadlet on the local bus
*
* \param Id Identfies the device
* \param Adr Offset of the register
* \return
* Returns the quadlet read.
* \throw BcamException on failure.
*/
//------------------------------------------------------------------------------
ULONG CBcamAdapter::ReadQuad( ID Id, LARGE_INTEGER Adr )
{
BOOL ret;
ULONG numBytes;
DWORD err;
BaccArgReadQuad arg;
BaccResReadQuad res;
arg.Adr.NodeID = (USHORT) Id;
arg.Adr.Adr_High = (USHORT) Adr.HighPart;
arg.Adr.Adr_Low = Adr.LowPart;
BcamAdapterOL *pOl = GetNewBcamAdapterOL();
ret = DeviceIoControl( m_hDevice,
IOCTL_BACC_READ_QUAD,
&arg, sizeof arg,
&res, sizeof res,
&numBytes,
&pOl->ol // NULL
);
err = GetLastError();
if (!ret && err == ERROR_IO_PENDING)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -