WinCE虚拟串口驱动(二)

//========================================================================
  //TITLE:
  //    WinCE虚拟串口驱动(二)
  //AUTHOR:
  //    norains
  //DATE:
  //    Saturday 28-March-2009
  //Environment:
  //    WINDOWS CE 5.0
  //========================================================================
  虚拟串口驱动的完整代码如下:
view plaincopy to clipboardprint?
// VirtualSerial.cpp : Defines the entry point for the DLL application.  
//  
#include "windows.h"  
#include "reg.h"  
#include   
#include   
#include "algorithm"  
//--------------------------------------------------------------------------  
//Macro  
#define REG_ROOT_KEY     HKEY_LOCAL_MACHINE  
#define REG_DEVICE_SUB_KEY  TEXT("Drivers//Builtin//VirtualSerial")  
#define REG_MAP_PORT_NAME   TEXT("Map_Port")  
//The buffer length for storing the read data.  
#define READ_BUFFER_LENGTH  MAX_PATH  
//--------------------------------------------------------------------------  
//Gloabal variable  
HANDLE g_hCom = INVALID_HANDLE_VALUE;  
unsigned int g_uiOpenCount = 0;  
CRITICAL_SECTION g_csOpen;  
CRITICAL_SECTION g_csRead;  
CRITICAL_SECTION g_csWrite;  
std::vector g_vtBufRead(READ_BUFFER_LENGTH,0);  
DWORD g_dwLenReadBuf = 0;  
DWORD g_dwEvtMask = 0;  
DWORD g_dwWaitMask = 0;  
HANDLE g_hEventComm = NULL;  
BOOL g_bMonitorProcRunning = FALSE;  
BOOL g_bExitMonitorProc = FALSE;  
BOOL g_bReaded = FALSE;  
//--------------------------------------------------------------------------  
BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)  
{  
    switch ( dwReason )   
    {  
        case DLL_PROCESS_ATTACH:  
        break;  
    }  
    return TRUE;  
}  
DWORD MonitorCommEventProc(LPVOID pParam)  
{  
InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),TRUE);  
RETAILMSG(TRUE,(TEXT("[VSP]:MonitorCommEventProc Running!/r/n")));  
std::vector vtBufRead(g_vtBufRead.size(),0);    
while(TRUE)  
{   
  DWORD dwEvtMask = 0;  
  BOOL bWaitRes = WaitCommEvent(g_hCom,&dwEvtMask,NULL);      
  if(g_bExitMonitorProc != FALSE)  
  {  
   break;  
  }       
  if(bWaitRes == FALSE)  
  {  
   continue;  
  }    
  DWORD dwRead = 0;     
  if(dwEvtMask & EV_RXCHAR)  
  {  
   EnterCriticalSection(&g_csRead);       
   ReadFile(g_hCom,&g_vtBufRead[0],vtBufRead.size(),&dwRead,NULL);    
   if(dwRead == vtBufRead.size() || g_bReaded != FALSE)  
   {  
    g_dwLenReadBuf = dwRead;  
    g_vtBufRead.swap(vtBufRead);  
   }  
   else if(dwRead != 0)  
   {  
    if(g_dwLenReadBuf + dwRead <= g_vtBufRead.size())  
    {  
     g_dwLenReadBuf += dwRead;  
     g_vtBufRead.insert(g_vtBufRead.end(),vtBufRead.begin(),vtBufRead.begin() + dwRead);  
    }  
    else 
    {  
     DWORD dwCover = g_dwLenReadBuf + dwRead - g_vtBufRead.size();  
     std::copy(g_vtBufRead.begin() + dwCover,g_vtBufRead.begin() + g_dwLenReadBuf,g_vtBufRead.begin());  
     std::copy(vtBufRead.begin(),vtBufRead.begin() + dwRead,g_vtBufRead.begin() + (g_dwLenReadBuf - dwCover));  
     g_dwLenReadBuf = g_vtBufRead.size();  
    }  
   }  
   g_bReaded = FALSE;  
   DEBUGMSG(TRUE,(TEXT("[VSP]:Read data : %d/r/n"),dwRead));   
   LeaveCriticalSection(&g_csRead);  
  }  
  if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 || dwRead == 0))  
  {  
   //The return event mask is only EV_RXCHAR and there is not EV_RXCHAR in the wait mask.  
   continue;  
  }  
  InterlockedExchange(reinterpret_cast (&g_dwEvtMask),dwEvtMask);  
  PulseEvent(g_hEventComm);    
  //Sleep for other thread to respond to the event  
  Sleep(100);  
  DEBUGMSG(TRUE,(TEXT("[VSP]:PulseEvent! The event-mask is 0x%x/r/n"),dwEvtMask));   
}  
RETAILMSG(TRUE,(TEXT("[VSP]:Exit the MonitorCommEventProc/r/n")));   
InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),FALSE);  
return 0;  
}  
BOOL VSP_Close(DWORD dwHandle)  
{  
EnterCriticalSection(&g_csOpen);  
g_uiOpenCount --;   
if(g_uiOpenCount == 0)  
{    
  //Notify the monitor thread to exit.   
  InterlockedExchange(reinterpret_cast (&g_bExitMonitorProc),TRUE);  
  DWORD dwMask = 0;  
  GetCommMask(g_hCom,&dwMask);  
  SetCommMask(g_hCom,dwMask);    
  while(InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),TRUE) == TRUE)  
  {  
   Sleep(20);  
  }  
  InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),FALSE);  
  CloseHandle(g_hCom);  
  g_hCom = NULL;  
}  
LeaveCriticalSection(&g_csOpen);  
return TRUE;  
}  
DWORD VSP_Init(DWORD dwContext)  
{  
RETAILMSG(TRUE,(TEXT("[+VSP_Init]/r/n")));   
InitializeCriticalSection(&g_csOpen);  
InitializeCriticalSection(&g_csRead);  
InitializeCriticalSection(&g_csWrite);  
g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);  
RETAILMSG(TRUE,(TEXT("[-VSP_Init]/r/n")));  
return TRUE;  
}  
BOOL VSP_Deinit(  
    DWORD dwContext     // future: pointer to the per disk structure  
    )  
{  
RETAILMSG(TRUE,(TEXT("[+VSP_Deinit]/r/n")));   
CloseHandle(g_hEventComm);  
g_hEventComm = NULL;  
DeleteCriticalSection(&g_csOpen);  
DeleteCriticalSection(&g_csRead);  
DeleteCriticalSection(&g_csWrite);  
RETAILMSG(TRUE,(TEXT("[-VSP_Deinit]/r/n")));   
return TRUE;  
}  
DWORD VSP_Open(  
    DWORD dwData,  
    DWORD dwAccess,  
    DWORD dwShareMode  
    )  
{  
BOOL bResult = FALSE;  
EnterCriticalSection(&g_csOpen);  
//The variable  
CReg reg;  
std::vector vtBuf(MAX_PATH,0);  
COMMPROP commProp = {0};  
if(g_uiOpenCount != 0)  
{    
  goto SET_SUCCEED_FLAG;  
}   
if(reg.Open(REG_ROOT_KEY,REG_DEVICE_SUB_KEY) == FALSE)  
{  
  RETAILMSG(TRUE,(TEXT("[VSP]:Failed to open the registry/r/n")));  
  goto LEAVE_CRITICAL_SECTION;  
}  
//Get the MAP_PORT name   
reg.GetValueSZ(REG_MAP_PORT_NAME,&vtBuf[0],vtBuf.size());  
g_hCom = CreateFile(&vtBuf[0],GENERIC_READ | GENERIC_WRITE ,0,NULL,OPEN_EXISTING,0,NULL);  
if(g_hCom == INVALID_HANDLE_VALUE )  
{  
  RETAILMSG(TRUE,(TEXT("[VSP]Failed to map to %s/r/n"),&vtBuf[0]));  
  goto LEAVE_CRITICAL_SECTION;  
}  
else 
{  
  RETAILMSG(TRUE,(TEXT("[VSP]Succeed to map to %s/r/n"),&vtBuf[0]));  
}   
InterlockedExchange(reinterpret_cast (&g_bExitMonitorProc),FALSE);  
CloseHandle(CreateThread(NULL,NULL,MonitorCommEventProc,NULL,NULL,NULL));  
SET_SUCCEED_FLAG:  
g_uiOpenCount ++;  
bResult = TRUE;  
LEAVE_CRITICAL_SECTION:   
LeaveCriticalSection(&g_csOpen);  
return bResult;  
}  
BOOL VSP_IOControl(  
    DWORD dwHandle,  
    DWORD dwIoControlCode,  
    PBYTE pBufIn,  
    DWORD dwBufInSize,  
    PBYTE pBufOut,  
    DWORD dwBufOutSize,  
    PDWORD pBytesReturned  
    )  
{   
switch(dwIoControlCode)  
{  
  case IOCTL_SERIAL_SET_DCB:  
  {     
   return SetCommState(g_hCom,reinterpret_cast (pBufIn));  
  }  
  case IOCTL_SERIAL_GET_DCB:  
  {     
   return GetCommState(g_hCom,reinterpret_cast (pBufOut));  
  }  
  case IOCTL_SERIAL_WAIT_ON_MASK:  
  {      
   if(dwBufOutSize < sizeof(DWORD) ||  WaitForSingleObject(g_hEventComm,INFINITE) == WAIT_TIMEOUT)  
   {  
    *pBytesReturned = 0;     
    return FALSE;  
   }  
   else 
   {  
    InterlockedExchange(reinterpret_cast (pBufOut),g_dwEvtMask);  
    *pBytesReturned = sizeof(DWORD);        
    return TRUE;  
   }       
  }  
  case IOCTL_SERIAL_SET_WAIT_MASK:  
  {    
   g_dwWaitMask = *reinterpret_cast (pBufIn);  
   return SetCommMask(g_hCom,g_dwWaitMask | EV_RXCHAR); //The driver need the EV_RXCHAR notify event.  
  }  
  case IOCTL_SERIAL_GET_WAIT_MASK:  
  {     
   if(dwBufOutSize < sizeof(DWORD) || GetCommMask(g_hCom,reinterpret_cast (pBufOut)) == FALSE)  
   {  
    *pBytesReturned = 0;     
    return FALSE;  
   }  
   else 
   {  
    *pBytesReturned = sizeof(DWORD);  
    return TRUE;  
   }  
  }  
}  
return FALSE;  
}  
DWORD VSP_Read(DWORD dwHandle, LPVOID pBuffer, DWORD dwNumBytes)  
{  
EnterCriticalSection(&g_csRead);    
//The g_dwLenReadBuf must be less than or equal to g_vtBufRead.size(), so needn't compare with each other.  
DWORD dwCopy = g_dwLenReadBuf > dwNumBytes ? dwNumBytes : g_dwLenReadBuf;  
if(dwCopy != 0)  
{  
  memcpy(pBuffer,&g_vtBufRead[0],dwCopy);  
}    
DEBUGMSG(TRUE,(TEXT("[VSP]:Copy cout:%d/r/n"),dwCopy));  
g_bReaded = TRUE;  
LeaveCriticalSection(&g_csRead);  
//Sleep for other thread to entry the function.  
Sleep(10);   
return dwCopy;  
}  
DWORD VSP_Write(DWORD dwHandle, LPCVOID pBuffer, DWORD dwNumBytes)  
{  
EnterCriticalSection(&g_csWrite);  
DWORD dwWrite = 0;  
WriteFile(g_hCom,pBuffer,dwNumBytes,&dwWrite,NULL);  
LeaveCriticalSection(&g_csWrite);  
return dwWrite;  
}  
DWORD VSP_Seek(DWORD dwHandle, long lDistance, DWORD dwMoveMethod)  
{  
return FALSE;  
}  
void VSP_PowerUp(void)  
{  
return;  
}  
void VSP_PowerDown(void)  
{  
return;  

// VirtualSerial.cpp : Defines the entry point for the DLL application.
//

#include "windows.h"
#include "reg.h"
#include
#include
#include "algorithm"

//--------------------------------------------------------------------------
//Macro
#define REG_ROOT_KEY     HKEY_LOCAL_MACHINE
#define REG_DEVICE_SUB_KEY  TEXT("Drivers//Builtin//VirtualSerial")
#define REG_MAP_PORT_NAME   TEXT("Map_Port")

//The buffer length for storing the read data.
#define READ_BUFFER_LENGTH  MAX_PATH
//--------------------------------------------------------------------------
//Gloabal variable
HANDLE g_hCom = INVALID_HANDLE_VALUE;
unsigned int g_uiOpenCount = 0;
CRITICAL_SECTION g_csOpen;
CRITICAL_SECTION g_csRead;
CRITICAL_SECTION g_csWrite;
std::vector g_vtBufRead(READ_BUFFER_LENGTH,0);
DWORD g_dwLenReadBuf = 0;
DWORD g_dwEvtMask = 0;
DWORD g_dwWaitMask = 0;
HANDLE g_hEventComm = NULL;
BOOL g_bMonitorProcRunning = FALSE;
BOOL g_bExitMonitorProc = FALSE;
BOOL g_bReaded = FALSE;
//--------------------------------------------------------------------------

BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
    switch ( dwReason )
    {
        case DLL_PROCESS_ATTACH:
        break;
    }
    return TRUE;
}

DWORD MonitorCommEventProc(LPVOID pParam)
{
InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),TRUE);
RETAILMSG(TRUE,(TEXT("[VSP]:MonitorCommEventProc Running!/r/n")));
std::vector vtBufRead(g_vtBufRead.size(),0); 
while(TRUE)
{
  DWORD dwEvtMask = 0;
  BOOL bWaitRes = WaitCommEvent(g_hCom,&dwEvtMask,NULL);   
  if(g_bExitMonitorProc != FALSE)
  {
   break;
  }    
  if(bWaitRes == FALSE)
  {
   continue;
  } 
  DWORD dwRead = 0;  
  if(dwEvtMask & EV_RXCHAR)
  {
   EnterCriticalSection(&g_csRead);    
   ReadFile(g_hCom,&g_vtBufRead[0],vtBufRead.size(),&dwRead,NULL); 
   if(dwRead == vtBufRead.size() || g_bReaded != FALSE)
   {
    g_dwLenReadBuf = dwRead;
    g_vtBufRead.swap(vtBufRead);
   }
   else if(dwRead != 0)
   {
    if(g_dwLenReadBuf + dwRead <= g_vtBufRead.size())
    {
     g_dwLenReadBuf += dwRead;
     g_vtBufRead.insert(g_vtBufRead.end(),vtBufRead.begin(),vtBufRead.begin() + dwRead);
    }
    else
    {
     DWORD dwCover = g_dwLenReadBuf + dwRead - g_vtBufRead.size();
     std::copy(g_vtBufRead.begin() + dwCover,g_vtBufRead.begin() + g_dwLenReadBuf,g_vtBufRead.begin());
     std::copy(vtBufRead.begin(),vtBufRead.begin() + dwRead,g_vtBufRead.begin() + (g_dwLenReadBuf - dwCover));
     g_dwLenReadBuf = g_vtBufRead.size();
    }
   }
   g_bReaded = FALSE;
   DEBUGMSG(TRUE,(TEXT("[VSP]:Read data : %d/r/n"),dwRead));
   LeaveCriticalSection(&g_csRead);
  }
  if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 || dwRead == 0))
  {
   //The return event mask is only EV_RXCHAR and there is not EV_RXCHAR in the wait mask.
   continue;
  }
  InterlockedExchange(reinterpret_cast (&g_dwEvtMask),dwEvtMask);
  PulseEvent(g_hEventComm); 
  //Sleep for other thread to respond to the event
  Sleep(100);
  DEBUGMSG(TRUE,(TEXT("[VSP]:PulseEvent! The event-mask is 0x%x/r/n"),dwEvtMask));
}
RETAILMSG(TRUE,(TEXT("[VSP]:Exit the MonitorCommEventProc/r/n")));
InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),FALSE);
return 0;
}

BOOL VSP_Close(DWORD dwHandle)
{
EnterCriticalSection(&g_csOpen);
g_uiOpenCount --;
if(g_uiOpenCount == 0)

  //Notify the monitor thread to exit.
  InterlockedExchange(reinterpret_cast (&g_bExitMonitorProc),TRUE);
  DWORD dwMask = 0;
  GetCommMask(g_hCom,&dwMask);
  SetCommMask(g_hCom,dwMask); 
  while(InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),TRUE) == TRUE)
  {
   Sleep(20);
  }
  InterlockedExchange(reinterpret_cast (&g_bMonitorProcRunning),FALSE);
  CloseHandle(g_hCom);
  g_hCom = NULL;
}

LeaveCriticalSection(&g_csOpen);
return TRUE;
}

DWORD VSP_Init(DWORD dwContext)
{
RETAILMSG(TRUE,(TEXT("[+VSP_Init]/r/n")));
InitializeCriticalSection(&g_csOpen);
InitializeCriticalSection(&g_csRead);
InitializeCriticalSection(&g_csWrite);
g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);
RETAILMSG(TRUE,(TEXT("[-VSP_Init]/r/n")));
return TRUE;
}

BOOL VSP_Deinit(
    DWORD dwContext     // future: pointer to the per disk structure
    )
{
RETAILMSG(TRUE,(TEXT("[+VSP_Deinit]/r/n")));
CloseHandle(g_hEventComm);
g_hEventComm = NULL;
DeleteCriticalSection(&g_csOpen);
DeleteCriticalSection(&g_csRead);
DeleteCriticalSection(&g_csWrite);
RETAILMSG(TRUE,(TEXT("[-VSP_Deinit]/r/n")));
return TRUE;
}

DWORD VSP_Open(
    DWORD dwData,
    DWORD dwAccess,
    DWORD dwShareMode
    )
{
BOOL bResult = FALSE;
EnterCriticalSection(&g_csOpen);
//The variable
CReg reg;
std::vector vtBuf(MAX_PATH,0);
COMMPROP commProp = {0};
if(g_uiOpenCount != 0)

  goto SET_SUCCEED_FLAG;
}
if(reg.Open(REG_ROOT_KEY,REG_DEVICE_SUB_KEY) == FALSE)
{
  RETAILMSG(TRUE,(TEXT("[VSP]:Failed to open the registry/r/n")));
  goto LEAVE_CRITICAL_SECTION;
}
//Get the MAP_PORT name
reg.GetValueSZ(REG_MAP_PORT_NAME,&vtBuf[0],vtBuf.size());
g_hCom = CreateFile(&vtBuf[0],GENERIC_READ | GENERIC_WRITE ,0,NULL,OPEN_EXISTING,0,NULL);
if(g_hCom == INVALID_HANDLE_VALUE )
{
  RETAILMSG(TRUE,(TEXT("[VSP]Failed to map to %s/r/n"),&vtBuf[0]));
  goto LEAVE_CRITICAL_SECTION;
}
else
{
  RETAILMSG(TRUE,(TEXT("[VSP]Succeed to map to %s/r/n"),&vtBuf[0]));
}
InterlockedExchange(reinterpret_cast (&g_bExitMonitorProc),FALSE);
CloseHandle(CreateThread(NULL,NULL,MonitorCommEventProc,NULL,NULL,NULL));
SET_SUCCEED_FLAG:
g_uiOpenCount ++;
bResult = TRUE;
LEAVE_CRITICAL_SECTION:
LeaveCriticalSection(&g_csOpen);
return bResult;
}

BOOL VSP_IOControl(
    DWORD dwHandle,
    DWORD dwIoControlCode,
    PBYTE pBufIn,
    DWORD dwBufInSize,
    PBYTE pBufOut,
    DWORD dwBufOutSize,
    PDWORD pBytesReturned
    )
{
switch(dwIoControlCode)
{
  case IOCTL_SERIAL_SET_DCB:
  {  
   return SetCommState(g_hCom,reinterpret_cast (pBufIn));
  }
  case IOCTL_SERIAL_GET_DCB:
  {  
   return GetCommState(g_hCom,reinterpret_cast (pBufOut));
  }
  case IOCTL_SERIAL_WAIT_ON_MASK:
  {   
   if(dwBufOutSize < sizeof(DWORD) ||  WaitForSingleObject(g_hEventComm,INFINITE) == WAIT_TIMEOUT)
   {
    *pBytesReturned = 0;  
    return FALSE;
   }
   else
   {
    InterlockedExchange(reinterpret_cast (pBufOut),g_dwEvtMask);
    *pBytesReturned = sizeof(DWORD);     
    return TRUE;
   }    
  }
  case IOCTL_SERIAL_SET_WAIT_MASK:
  { 
   g_dwWaitMask = *reinterpret_cast (pBufIn);
   return SetCommMask(g_hCom,g_dwWaitMask | EV_RXCHAR); //The driver need the EV_RXCHAR notify event.
  }
  case IOCTL_SERIAL_GET_WAIT_MASK:
  {  
   if(dwBufOutSize < sizeof(DWORD) || GetCommMask(g_hCom,reinterpret_cast (pBufOut)) == FALSE)
   {
    *pBytesReturned = 0;  
    return FALSE;
   }
   else
   {
    *pBytesReturned = sizeof(DWORD);
    return TRUE;
   }
  }
}
return FALSE;
}

DWORD VSP_Read(DWORD dwHandle, LPVOID pBuffer, DWORD dwNumBytes)
{
EnterCriticalSection(&g_csRead); 
//The g_dwLenReadBuf must be less than or equal to g_vtBufRead.size(), so needn't compare with each other.
DWORD dwCopy = g_dwLenReadBuf > dwNumBytes ? dwNumBytes : g_dwLenReadBuf;
if(dwCopy != 0)
{
  memcpy(pBuffer,&g_vtBufRead[0],dwCopy);

DEBUGMSG(TRUE,(TEXT("[VSP]:Copy cout:%d/r/n"),dwCopy));

g_bReaded = TRUE;
LeaveCriticalSection(&g_csRead);
//Sleep for other thread to entry the function.
Sleep(10);
return dwCopy;
}

DWORD VSP_Write(DWORD dwHandle, LPCVOID pBuffer, DWORD dwNumBytes)
{
EnterCriticalSection(&g_csWrite);
DWORD dwWrite = 0;
WriteFile(g_hCom,pBuffer,dwNumBytes,&dwWrite,NULL);
LeaveCriticalSection(&g_csWrite);
return dwWrite;
}

DWORD VSP_Seek(DWORD dwHandle, long lDistance, DWORD dwMoveMethod)
{
return FALSE;
}

void VSP_PowerUp(void)
{
return;
}

void VSP_PowerDown(void)
{
return;
}

  不过该驱动代码是作者量身定做的,像IOControl就简单地实现了几个,其余的因为在实际使用中本人没用到,所以都没实现,只是简单地返回了FALSE。如果有朋友对此有兴趣,并且实际中也使用到,可以自行调用原生函数实现。
  最后,是能让驱动正常挂载的注册表设置:
[HKEY_LOCAL_MACHINE/Drivers/Builtin/VirtualSerial]
    "Prefix"="VSP"
    "Dll"="VirtualSerial.dll"
    "Order"=dword:0
    "Index"=dword:1
    "Map_Port"="COM1:"

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/norains/archive/2009/03/28/4032332.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值