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

📄 bcamadapter.cpp

📁 BCAM 1394 Driver
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    );
  
  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 + -