📄 bcamadapter.cpp
字号:
//-----------------------------------------------------------------------------
// Company: Basler Vision Technologies
// Section: Vision Components
// Project: 1394 Driver
// Subproject: Bus Access Driver
// $Header: BcamAdapter.cpp, 35, 06.07.2006 10:20:30, Nebelung, H.$
//-----------------------------------------------------------------------------
/**
\file BcamAdapter.cpp
\brief Implementation of the classes CBcamAdapter and CNode
*/
//-----------------------------------------------------------------------------
#include <stdafx.h>
#pragma warning( disable: 4786) // identifier was truncated to '255' characters in the browser information
#pragma warning (disable: 4702) // unreachable code
#include "Bcam.h"
#include <setupapi.h>
#include <bacc_guid.h>
#include <BcamAdapter.h>
#ifndef BACC_GUID_INITIALIZED
#include <initguid.h>
#include <bacc_guid.h>
#endif
#include <malloc.h>
#include <assert.h>
#include <bitset>
using namespace std;
using namespace Bcam;
// we use the ATL implementation of InterlockedExchangePointer because of problems with the one in system headers
#if defined( _M_IX86 ) && ! defined(__ATLCONV_H__) || (_ATL_VER == 0x300)
#undef InterlockedExchangePointer
inline void* WINAPI InterlockedExchangePointer(void** pp, void* pNew) throw()
{
return( reinterpret_cast<void*>( static_cast<long>( ::InterlockedExchange( reinterpret_cast<LONG*>( pp ), static_cast<LONG>( reinterpret_cast<long>( pNew ) ) ) ) ) );
}
#endif
enum {
Topology = 123
};
struct /*Bcam::*/BcamAdapterOL
{
OVERLAPPED ol; ///< Win32-Api defined structure, needed for all calls
Bcam::FunctionCode_t function; ///< Function code to identify the function called
BaccResGetTopology *pTopology;
PVOID pContext; ///< Pointer to user provided context
};
//------------------------------------------------------------------------------
// static BcamOL* GetNewBcamBcamOL( FunctionCode_t func, PVOID pContext )
// Author: Hartmut nebelung
//------------------------------------------------------------------------------
/**
* \brief Create a BcamAdapterOL structure on the heap and initializes it.
*
* \param func The function code to identify the call.
* \param pContext The user defined context, may be NULL.
* \return
*
* Returns an initialized BcamOL structure.
*
*/
//------------------------------------------------------------------------------
static BcamAdapterOL* GetNewBcamAdapterOL( HANDLE hEvent, FunctionCode_t func, BaccResGetTopology *pRes, PVOID pContext )
{
BcamAdapterOL* p = new BcamAdapterOL;
if (NULL == p)
throw BcamException( Bvc::ErrorNumber( E_OUTOFMEMORY ), _T( "GetNewBcamAdapterOL" ) );
p->ol.hEvent = hEvent;
p->ol.Internal = 0;
p->ol.InternalHigh = 0;
p->ol.Offset = 0;
p->ol.OffsetHigh = 0;
p->pTopology = pRes;
p->pContext = pContext;
p->function = func;
return p;
}
static BcamAdapterOL* GetNewBcamAdapterOL( )
{
BcamAdapterOL* p = new BcamAdapterOL;
if (NULL == p)
throw BcamException( Bvc::ErrorNumber( E_OUTOFMEMORY ), _T( "GetNewBcamAdapterOL" ) );
p->ol.hEvent = NULL;
p->ol.Internal = 0;
p->ol.InternalHigh = 0;
p->ol.Offset = 0;
p->ol.OffsetHigh = 0;
p->pTopology = NULL;
p->pContext = NULL;
p->function = (FunctionCode_t) 0;
return p;
}
// 1394api.h ++
//
// 1394 Add/Remove Virtual Device format
//
typedef struct _VIRT_DEVICE {
ULONG fulFlags;
ULARGE_INTEGER InstanceID;
PSTR DeviceID;
} VIRT_DEVICE, *PVIRT_DEVICE;
// 1394api.h --
// 1394.h ++
//
// Definitions of Speed flags used throughout 1394 Bus APIs
//
#define SPEED_FLAGS_100 0x01
#define SPEED_FLAGS_200 0x02
#define SPEED_FLAGS_400 0x04
#define SPEED_FLAGS_800 0x08
#define SPEED_FLAGS_1600 0x10
#define SPEED_FLAGS_3200 0x20
#define SPEED_FLAGS_FASTEST 0x80000000
// 1394.h --
// ntdd1394.h ++
#ifdef __cplusplus
extern "C" {
#endif
//
// registry definitions
//
#define BUS1394_VIRTUAL_DEVICE_LIST_KEY L"Virtual Device List"
#define BUS1394_LOCAL_HOST_INSTANCE_KEY L"LOCAL HOST EUI64"
//
// Various definitions
//
#define IOCTL_IEEE1394_API_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
0x100, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS \
)
//
// IEEE 1394 Sbp2 Request packet. It is how other
// device drivers communicate with the 1sbp2 trasnport.
//
typedef struct _IEEE1394_VDEV_PNP_REQUEST{
ULONG fulFlags;
ULONG Reserved;
ULARGE_INTEGER InstanceId;
UCHAR DeviceId;
} IEEE1394_VDEV_PNP_REQUEST,*PIEEE1394_VDEV_PNP_REQUEST;
typedef struct _IEEE1394_API_REQUEST {
//
// Holds the zero based Function number that corresponds to the request
// that device drivers are asking the sbp2 port driver to carry out.
//
ULONG RequestNumber;
//
// Holds Flags that may be unique to this particular operation
//
ULONG Flags;
//
// Holds the structures used in performing the various 1394 APIs
//
union {
IEEE1394_VDEV_PNP_REQUEST AddVirtualDevice;
IEEE1394_VDEV_PNP_REQUEST RemoveVirtualDevice;
} u;
} IEEE1394_API_REQUEST, *PIEEE1394_API_REQUEST;
//
// Request Number
//
#define IEEE1394_API_ADD_VIRTUAL_DEVICE 0x00000001
#define IEEE1394_API_REMOVE_VIRTUAL_DEVICE 0x00000002
//
// flags for the add/remove requests
//
#define IEEE1394_REQUEST_FLAG_UNICODE 0x00000001
#define IEEE1394_REQUEST_FLAG_PERSISTENT 0x00000002
#define IEEE1394_REQUEST_FLAG_USE_LOCAL_HOST_EUI 0x00000004
//
// definitions for the access/ownership 1394 scheme
//
#ifdef __cplusplus
}
#endif
// ntdd1394.h --
#ifndef TRACE
/// In case we are using WTL replace TRACE calls by AtlTrace
#define TRACE AtlTrace
#endif
#define E_MEMORY E_OUTOFMEMORY
//////////////////////////////////////////////////////////////////////
/// Possible values of port connection state
enum PortConnection
{
Not_Present = 0, ///< Port is not present
Not_Connected = 1, ///< Port is not connected
Connected_to_Parent = 2, ///< Port is connected to parent
Connected_to_Child = 3 ///< Port is connected to child
};
//------------------------------------------------------------------------------
// static inline ULONG GetPortState( NODE *pn, size_t port )
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Connection state of a port
*
* \param *pn Pointer to the node array
* \param port Number of the port
* \return
*
* connection state
*
*/
//------------------------------------------------------------------------------
static ULONG GetPortState( NODE *pn, size_t port )
{
const unsigned _Nb = PORTS_PER_DWORD;
const PULONG _A = pn->Ports;
assert( port <= MAX_PORTS );
return (_A[port / _Nb] >> 2 * (port % _Nb)) & PORT_MASK;
}
/////////////////////////////////////////////////////////////////////
/**
* \brief Analyze result of device I/O control call
*
* \param b result of a device I/O control call
* \return true if failed, false otherwise
*/
//------------------------------------------------------------------------------
inline bool FailedDevIO( BOOL b )
{
return b == 0;
}
//------------------------------------------------------------------------------
// bool IsFullDeviceName(CString DeviceName)
// Author:
// Date: 26.10.2002
//------------------------------------------------------------------------------
/**
* \brief is a given device name a "full" device name, i.e. does it contain the driver interface GUID?
*
* Check if a given device name is a full device name (as it is passed in by the plug and play manager)
* or if it is a friendly device name not containing the driver interface GUID
*
* \param DeviceName device name to check
* \return true, if the device name is not a friendly device name
*
*/
//------------------------------------------------------------------------------
static bool IsFullDeviceName(CString DeviceName)
{
int first = DeviceName.Find('#');
assert(first > 0);
int l = DeviceName.GetLength();
int second = DeviceName.Right(l - (first+1)).Find('#') + first + 1;
return(second > first);
}
//------------------------------------------------------------------------------
// CString FullDeviceName(CString DeviceName)
// Author:
// Date: 8.1.2003
//------------------------------------------------------------------------------
/**
* \brief given a friendly device name return a full device name
*
* Friendly device names don't contain the driver's interface GUID. This function
* converts a friendly device name into a full device name,
* as it is used by the system.
*
* \param DeviceName a friendly device name
* \return the full device name
*
*/
//------------------------------------------------------------------------------
static CString FullDeviceName( CString DeviceName )
{
if (!IsFullDeviceName( DeviceName ))
{
struct _GUID guid = GUID_BACC_DEVICE;
CString guidString;
guidString.Format( _T( "#{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}" ),
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
return _T( "\\\\?\\v1394#" ) + DeviceName + guidString;
}
else return DeviceName;
}
//------------------------------------------------------------------------------
// CString FriendlyDeviceName(CString DeviceName)
// Date: 26.10.2002
//------------------------------------------------------------------------------
/**
* \brief Retrieves the friendly device name for a given full device name
*
* Friendly device names don't contain the driver's interface GUID. This
* function converts a full device named used by the system into a
* friendly device name
*
* \param DeviceName the full device name
* \return the friendly device name
*
*/
//------------------------------------------------------------------------------
static CString FriendlyDeviceName( CString DeviceName )
{
if (IsFullDeviceName( DeviceName ))
{
int first = DeviceName.Find('#');
assert(first > 0);
int l = DeviceName.GetLength();
int second = DeviceName.Right(l - (first+1)).Find('#') + first + 1;
assert(second > 0);
int third = DeviceName.Right(l - (second+1)).Find('#') + second + 1;
assert(third > 0);
assert(DeviceName[third+1] == '{');
return DeviceName.Left(third).Right(third-(first+1));
}
else return DeviceName;
}
using namespace std;
using namespace Bcam;
CTopology::CTopology( unsigned long initialSize )
:
m_pTopology( NULL ),
m_pOL( NULL ),
m_IoPending( false )
{
m_Event.Create();
SetSize( initialSize );
}
CTopology::~CTopology()
{
delete []m_pTopology;
delete m_pOL;
}
CTopology::operator HANDLE()
{
return m_Event;
}
unsigned long CTopology::RequiredSize() const
{
if (! m_pTopology)
throw BcamException( Bvc::ErrorNumber( E_FAIL ), _T( "CTopology::RequiredSize" ) );
return ((BaccResGetTopology*)m_pTopology)->Size;
}
CBcamAdapter* CTopology::Attach( CBcamAdapter* p )
{
if (m_IoPending)
throw BcamException( Bvc::ErrorNumber( E_UNEXPECTED ), _T( "CTopology::Attach" ) );
return (CBcamAdapter*) InterlockedExchangePointer( (void**)&m_pAdapter, p );
}
CBcamAdapter* CTopology::Detach()
{
if (m_IoPending)
throw BcamException( Bvc::ErrorNumber( E_UNEXPECTED ), _T( "CTopology::Detach" ) );
return Attach( NULL );
}
void CTopology::SetSize( unsigned long Size )
{
if (m_pOL || m_IoPending)
throw BcamException( Bvc::ErrorNumber( E_UNEXPECTED ), _T( "CTopology::SetSize" ) );
if (Size < sizeof *m_pTopology)
Size = sizeof *m_pTopology;
void* pv = new BYTE[Size];
delete m_pTopology;
m_pTopology = (BaccResGetTopology*)pv;
m_pTopology->Size = Size;
}
unsigned long CTopology::Wait( unsigned long Timeout ) const
{
return WaitForSingleObject( m_Event, Timeout );
};
void CTopology::GetTreeRequest( void* pContext )
{
if (!m_pTopology || m_pOL || m_IoPending || !m_pAdapter)
throw BcamException( Bvc::ErrorNumber( E_UNEXPECTED ), _T( "CTopology::BuildTreeAsync" ) );
m_pOL = m_pAdapter->GetTreeAsync( m_Event, m_pTopology, pContext );
m_IoPending = true;
}
CNode* CTopology::GetTreeResponse( void**ppContext )
{
if (! m_IoPending || !m_pAdapter)
throw BcamException( Bvc::ErrorNumber( E_UNEXPECTED ), _T( "CTopology::GetTree" ) );
CNode *p = m_pAdapter->GetTree( m_pOL, ppContext );
m_IoPending = false;
delete m_pOL;
m_pOL = NULL;
if (m_pTopology->Status)
return NULL; // wrong buffer size
else
return p;
}
void CTopology::Cancel()
{
BOOL ret = CancelIo( m_pAdapter->GetDevice() );
if (FailedDevIO( ret ))
throw BcamException( ::GetLastError(), _T( "CTopology::Cancel" ) );
}
//------------------------------------------------------------------------------
// class CBcamDevCreator
// Author: HNebelun
//------------------------------------------------------------------------------
/**
* \brief Utility class helping to create Bcam Adapters
*
* The intention is to use a sigleton object, that creates for each 1394Bus object
* a 1394 Basler Virtual Device on construction and destroys them on destruction.
* The virtual devices can then be found in the DeviceManager in the 1394 Basler
* Virtual Device class entry.
*/
//------------------------------------------------------------------------------
class CBcamDevCreator
{
public:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -