WinCE虚拟串口驱动 二

               

   //========================================================================
  //TITLE:
  //    WinCE虚拟串口驱动(二)
  //AUTHOR:
  //    norains
  //DATE:
  //    Saturday 28-March-2009
  //Environment:
  //    WINDOWS CE 5.0
  //========================================================================
  
  虚拟串口驱动的完整代码如下:
  
// VirtualSerial.cpp : Defines the entry point for the DLL application.//#include "windows.h"#include "reg.h"#include <vector>#include <Pegdser.h>#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 variableHANDLE g_hCom = INVALID_HANDLE_VALUE;unsigned int g_uiOpenCount = 0;CRITICAL_SECTION g_csOpen;CRITICAL_SECTION g_csRead;CRITICAL_SECTION g_csWrite;std::vector<BYTE> 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<LONG *>(&g_bMonitorProcRunning),TRUE);  RETAILMSG(TRUE,(TEXT("[VSP]:MonitorCommEventProc Running!/r/n")));  std::vector<BYTE> 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<LONG *>(&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<LONG *>(&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<LONG *>(&g_bExitMonitorProc),TRUE);  DWORD dwMask = 0;  GetCommMask(g_hCom,&dwMask);  SetCommMask(g_hCom,dwMask);      while(InterlockedExchange(reinterpret_cast<LONG *>(&g_bMonitorProcRunning),TRUE) == TRUE)  {   Sleep(20);  }  InterlockedExchange(reinterpret_cast<LONG *>(&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<TCHAR> 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<LONG *>(&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<DCB *>(pBufIn));  }  case IOCTL_SERIAL_GET_DCB:  {      return GetCommState(g_hCom,reinterpret_cast<DCB *>(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<LONG *>(pBufOut),g_dwEvtMask);    *pBytesReturned = sizeof(DWORD);          return TRUE;   }       }  case IOCTL_SERIAL_SET_WAIT_MASK:  {     g_dwWaitMask = *reinterpret_cast<DWORD *>(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<DWORD *>(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:"

  

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值