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

📄 parallelport.cpp

📁 VC直接操作并行口 读写数据 VC直接操作并行口 读写数据
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
Module : PARALLEL.CPP
Purpose: Implementation for an MFC class to encapsulate parallel ports
Created: PJN / 28-12-1999
History: PJN / 06-03-2000 Code now throws an exception if no Win32 parallel ports are available
         PJN / 04-04-2000 Code handles the case where it is run on NT / Windows 2000 by throwing
                          an exception                 
         PJN / 19-07-2000 1. Now works on NT / Windows 2000 thanks to DriverLINX Port I/O Driver
                          2. Made all typedefs and enums local to the appropiate class rather
                          than polluting the global namespace


Copyright (c) 1999 - 2000 by PJ Naughter.  
All rights reserved.

*/

/////////////////////////////////  Includes  //////////////////////////////////
#include "stdafx.h"
#include "ParallelPort.h"
#include <winerror.h>
#include <conio.h>
#include <afxpriv.h>




///////////////////////////////// Defines / Statics ///////////////////////////

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

int CParallelPort::sm_nRefCount = 0;
BOOL CParallelPort::sm_bRunningOnNT = FALSE;
HINSTANCE CParallelPort::sm_hDLINX = NULL;
CParallelPort::LPDLPORTREADPORTUCHAR CParallelPort::sm_lpfnDlPortReadUchar = NULL;
CParallelPort::LPDLPORTWRITEPORTUCHAR CParallelPort::sm_lpfnDlPortWriteUchar = NULL;
CArray<CParallelPortSettings, CParallelPortSettings&> CParallelPort::sm_Ports;




//////////////////////////////// Implementation ///////////////////////////////


////////// Exception handling code

void AfxThrowParallelException(DWORD dwError /* = 0 */)
{
	if (dwError == 0)
		dwError = ::GetLastError();

	CParallelException* pException = new CParallelException(dwError);

	TRACE(_T("Warning: throwing CParallelException for error %d\n"), dwError);
	THROW(pException);
}

BOOL CParallelException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
{
	ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));

	if (pnHelpContext != NULL)
		*pnHelpContext = 0;

	LPTSTR lpBuffer;
	BOOL bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
			                      NULL,  m_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
			                      (LPTSTR) &lpBuffer, 0, NULL);

	if (bRet == FALSE)
		*pstrError = '\0';
	else
	{
		lstrcpyn(pstrError, lpBuffer, nMaxError);
		bRet = TRUE;

		LocalFree(lpBuffer);
	}

	return bRet;
}

CString CParallelException::GetErrorMessage()
{
  CString rVal;
  LPTSTR pstrError = rVal.GetBuffer(4096);
  GetErrorMessage(pstrError, 4096, NULL);
  rVal.ReleaseBuffer();
  return rVal;
}

CParallelException::CParallelException(DWORD dwError)
{
	m_dwError = dwError;
}

CParallelException::~CParallelException()
{
}

IMPLEMENT_DYNAMIC(CParallelException, CException)

#ifdef _DEBUG
void CParallelException::Dump(CDumpContext& dc) const
{
	CObject::Dump(dc);

	dc << "m_dwError = " << m_dwError;
}
#endif



////////// Settings class

CParallelPortSettings::CParallelPortSettings()
{
  m_nBaseAddress = 0;
  m_Type         = ParallelTypeUndefined;
  m_ECPMode      = ECPModeUndefined;
}

CParallelPortSettings::CParallelPortSettings(const CParallelPortSettings& state)
{
  *this = state;
}

CParallelPortSettings& CParallelPortSettings::operator=(const CParallelPortSettings& state)
{
  m_nBaseAddress = state.m_nBaseAddress;
  m_Type         = state.m_Type;   
  m_ECPMode      = state.m_ECPMode;

  return *this;
}



////////// The actual parallel port class

CParallelPort::CParallelPort()
{
  m_hPort = INVALID_HANDLE_VALUE;
  m_nPortIndex = -1;
  m_nBaseAddress = 0;
  m_dwTimeout = 1000;  //Default timeout is 1 second

  //Test for presence of parallel ports at the standard addresses of 0x3BC, 0x378 and 0x278
  if (sm_nRefCount == 0)
  {
    ++sm_nRefCount;

    //Initialize the DriverLINX driver if on NT / Windows 2000
    sm_bRunningOnNT = RunningOnNT();
    if (sm_bRunningOnNT)
    {
      if (!InitializeDriverLINX())
      {
        TRACE(_T("Running on Windows NT / Windows 2000 and the DriverLINX PORTIO driver is not installed, aborting !!\n"));
        AfxThrowParallelException();
      }
    }

    //Open LPT1 - LPT3 as a precaution against other processes trying to write 
    //to the port while we are detecting them
    HANDLE hPort1 = CreateFile(_T("\\\\.\\LPT1"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    HANDLE hPort2 = CreateFile(_T("\\\\.\\LPT2"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    HANDLE hPort3 = CreateFile(_T("\\\\.\\LPT3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    //Must have at least one port available in Win32 to continue to attempt
    //detection of the ports
    int nWin32Ports = 0;
    if (hPort1 != INVALID_HANDLE_VALUE)
      ++nWin32Ports;
    if (hPort2 != INVALID_HANDLE_VALUE)
      ++nWin32Ports;
    if (hPort3 != INVALID_HANDLE_VALUE)
      ++nWin32Ports;
    if (nWin32Ports == 0)
    {
      TRACE(_T("No parallel ports are available to Win32, aborting !!\n"));
      AfxThrowParallelException(ERROR_DEV_NOT_EXIST);
    }

    //Try to detect the details of the 3 standard ports
    CParallelPortSettings settings;
    if (GetPort(0x3BC, settings))
      sm_Ports.Add(settings);

    if (sm_Ports.GetSize() < nWin32Ports) 
      if (GetPort(0x378, settings))
        sm_Ports.Add(settings);

    if (sm_Ports.GetSize() < nWin32Ports) 
      if (GetPort(0x278, settings))
        sm_Ports.Add(settings);

    if (sm_Ports.GetSize() == 0)
      TRACE(_T("Could not detect any parallel ports on this machine\n"));

    //Don't forget to close the 3 SDK handles we had open
    CloseHandle(hPort3);
    CloseHandle(hPort2);
    CloseHandle(hPort1);
  }
}

CParallelPort::~CParallelPort()
{
  //decrement the reference count and 
  //free the DriverLINX pointers if necessary
  --sm_nRefCount;
  if (sm_nRefCount == 0)
    DeInitializeDriverLINX();

  Close();
}

IMPLEMENT_DYNAMIC(CParallelPort, CObject)

#ifdef _DEBUG
void CParallelPort::Dump(CDumpContext& dc) const
{
	CObject::Dump(dc);

	dc << _T("m_hPort = ") << m_hPort << _T("\n");
}
#endif

void CParallelPort::Open(int nPort)
{
  //Call Close just in case we already have the port open
  Close();

  m_nPortIndex = nPort - 1;
  if (m_nPortIndex < sm_Ports.GetSize())
  {
    //Cache the base address of the port for performance reasons
    m_nBaseAddress = sm_Ports.ElementAt(m_nPortIndex).m_nBaseAddress;

    //Call CreateFile to open up the parallel port. This prevents other apps 
    //causing problems when we do the Port IO directly.
    CString sPort;
    sPort.Format(_T("\\\\.\\LPT%d"), nPort);
    m_hPort = CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (m_hPort == INVALID_HANDLE_VALUE)
    {
      TRACE(_T("Failed to open parallel port, LPT%d\n"), nPort);
      Close();
      AfxThrowParallelException();
    }
  }
  else
  {
    TRACE(_T("Could not find the parallel port, LPT%d\n"), nPort);
    Close();
    AfxThrowParallelException(ERROR_FILE_NOT_FOUND);
  }
}

BOOL CParallelPort::IsOpen() const
{
  return (m_hPort != INVALID_HANDLE_VALUE);
}

void CParallelPort::Close()
{
  if (IsOpen())
  {
    BOOL bSuccess = CloseHandle(m_hPort);
    m_hPort = INVALID_HANDLE_VALUE;
    m_nPortIndex = -1;
    m_nBaseAddress = 0;
    if (!bSuccess)
      TRACE(_T("Failed to close the parallel port, GetLastError:%d\n"), GetLastError());
  }
}

void CParallelPort::SetECPMode(CParallelPortSettings::ECPPortMode mode)
{
  ASSERT(IsOpen()); //Port must be open 
  CParallelPortSettings& settings = sm_Ports.ElementAt(m_nPortIndex);
  ASSERT(settings.m_Type == CParallelPortSettings::ParallelTypeECP); //Must be an ECP port
  ASSERT(mode != CParallelPortSettings::ECPModeUndefined);

  unsigned short nEcrAddress = (unsigned short)(m_nBaseAddress + 0x402);

  //Read the ECR & clear bits 5, 6 & 7
  int nEcrData = _inp(nEcrAddress) & 0x1F;
  
  //Write the selected value to bits 5, 6 & 7
  switch (mode)
  {
    case CParallelPortSettings::ECPModeSPP:            nEcrData |= (0 << 5); break;
    case CParallelPortSettings::ECPModePS2:            nEcrData |= (1 << 5); break;
    case CParallelPortSettings::ECPModeFastCentronics: nEcrData |= (2 << 5); break;
    case CParallelPortSettings::ECPModeECP:            nEcrData |= (3 << 5); break;
    case CParallelPortSettings::ECPModeEPP:            nEcrData |= (4 << 5); break;
    case CParallelPortSettings::ECPModeTest:           nEcrData |= (6 << 5); break;
    case CParallelPortSettings::ECPModeConfiguration:  nEcrData |= (7 << 5); break;
    default: ASSERT(FALSE);                           break;
  }
  _outp(nEcrAddress, nEcrData);

  //Update the value in our cached array
  settings.m_ECPMode = mode;
}

CParallelPortSettings::ECPPortMode CParallelPort::GetECPMode()
{
  ASSERT(IsOpen()); //Port must be open 
  CParallelPortSettings& settings = sm_Ports.ElementAt(m_nPortIndex);
  ASSERT(settings.m_Type == CParallelPortSettings::ParallelTypeECP); //Must be an ECP port

  CParallelPortSettings::ECPPortMode t = ReadECPMode(settings.m_nBaseAddress);
  ASSERT(t == settings.m_ECPMode);

  return settings.m_ECPMode;
}

CParallelPortSettings::ECPPortMode CParallelPort::ReadECPMode(unsigned short nBaseAddress)
{
  CParallelPortSettings::ECPPortMode mode = CParallelPortSettings::ECPModeUndefined;
  int nEcrData = _inp((unsigned short)(nBaseAddress+0x402));
  nEcrData = (nEcrData & 0xE0) >> 5;
  switch (nEcrData)
  { 
    case 0: mode = CParallelPortSettings::ECPModeSPP;            break;
    case 1: mode = CParallelPortSettings::ECPModePS2;            break;
    case 2: mode = CParallelPortSettings::ECPModeFastCentronics; break;
    case 3: mode = CParallelPortSettings::ECPModeECP;            break;
    case 4: mode = CParallelPortSettings::ECPModeEPP;            break;
    case 6: mode = CParallelPortSettings::ECPModeTest;           break;
    case 7: mode = CParallelPortSettings::ECPModeConfiguration;  break;
    default: break;
  }
  return mode;
}

BOOL CParallelPort::GetPort(unsigned short nBaseAddress, CParallelPortSettings& settings)
{
  BOOL bSuccess = FALSE;

  //First try to detect an ECP port
  if (GetECPPort(nBaseAddress))
  {
    settings.m_nBaseAddress = nBaseAddress;
    settings.m_Type = CParallelPortSettings::ParallelTypeECP;
    settings.m_ECPMode = ReadECPMode(nBaseAddress);
    bSuccess = TRUE;
  }
  else
  {
    //If its not an ECP, look for an EPP.
    //If the baseaddress is 3BCh, skip the EPP test.
    //EPPs aren't allowed at 3BCh due to possible conflicts
    //with video memory
    BOOL bFoundEPP = FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -