WinCE虚拟串口驱动(二)

原文地址::http://blog.csdn.net/norains/article/details/4032332


 //========================================================================
  //TITLE:
  //    WinCE虚拟串口驱动(二)
  //AUTHOR:
  //    norains
  //DATE:
  //    Saturday 28-March-2009
  //Environment:
  //    WINDOWS CE 5.0
  //========================================================================
  
  虚拟串口驱动的完整代码如下:
  

[cpp]  view plain copy
  1. // VirtualSerial.cpp : Defines the entry point for the DLL application.  
  2. //  
  3.   
  4. #include "windows.h"  
  5. #include "reg.h"  
  6. #include <vector>  
  7. #include <Pegdser.h>  
  8. #include "algorithm"  
  9.   
  10. //--------------------------------------------------------------------------  
  11. //Macro  
  12. #define REG_ROOT_KEY     HKEY_LOCAL_MACHINE  
  13. #define REG_DEVICE_SUB_KEY  TEXT("Drivers//Builtin//VirtualSerial")  
  14. #define REG_MAP_PORT_NAME   TEXT("Map_Port")  
  15.   
  16. //The buffer length for storing the read data.  
  17. #define READ_BUFFER_LENGTH  MAX_PATH  
  18. //--------------------------------------------------------------------------  
  19. //Gloabal variable  
  20. HANDLE g_hCom = INVALID_HANDLE_VALUE;  
  21. unsigned int g_uiOpenCount = 0;  
  22. CRITICAL_SECTION g_csOpen;  
  23. CRITICAL_SECTION g_csRead;  
  24. CRITICAL_SECTION g_csWrite;  
  25. std::vector<BYTE> g_vtBufRead(READ_BUFFER_LENGTH,0);  
  26. DWORD g_dwLenReadBuf = 0;  
  27. DWORD g_dwEvtMask = 0;  
  28. DWORD g_dwWaitMask = 0;  
  29. HANDLE g_hEventComm = NULL;  
  30. BOOL g_bMonitorProcRunning = FALSE;  
  31. BOOL g_bExitMonitorProc = FALSE;  
  32. BOOL g_bReaded = FALSE;  
  33. //--------------------------------------------------------------------------  
  34.   
  35. BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)  
  36. {  
  37.     switch ( dwReason )   
  38.     {  
  39.         case DLL_PROCESS_ATTACH:  
  40.         break;  
  41.     }  
  42.     return TRUE;  
  43. }  
  44.   
  45. DWORD MonitorCommEventProc(LPVOID pParam)  
  46. {  
  47.  InterlockedExchange(reinterpret_cast<LONG *>(&g_bMonitorProcRunning),TRUE);  
  48.    
  49.  RETAILMSG(TRUE,(TEXT("[VSP]:MonitorCommEventProc Running!/r/n")));  
  50.    
  51.  std::vector<BYTE> vtBufRead(g_vtBufRead.size(),0);    
  52.  while(TRUE)  
  53.  {   
  54.   DWORD dwEvtMask = 0;  
  55.   BOOL bWaitRes = WaitCommEvent(g_hCom,&dwEvtMask,NULL);      
  56.     
  57.   if(g_bExitMonitorProc != FALSE)  
  58.   {  
  59.    break;  
  60.   }       
  61.     
  62.   if(bWaitRes == FALSE)  
  63.   {  
  64.    continue;  
  65.   }    
  66.     
  67.   DWORD dwRead = 0;     
  68.   if(dwEvtMask & EV_RXCHAR)  
  69.   {  
  70.    EnterCriticalSection(&g_csRead);       
  71.      
  72.    ReadFile(g_hCom,&g_vtBufRead[0],vtBufRead.size(),&dwRead,NULL);    
  73.    if(dwRead == vtBufRead.size() || g_bReaded != FALSE)  
  74.    {  
  75.     g_dwLenReadBuf = dwRead;  
  76.     g_vtBufRead.swap(vtBufRead);  
  77.    }  
  78.    else if(dwRead != 0)  
  79.    {  
  80.     if(g_dwLenReadBuf + dwRead <= g_vtBufRead.size())  
  81.     {  
  82.      g_dwLenReadBuf += dwRead;  
  83.      g_vtBufRead.insert(g_vtBufRead.end(),vtBufRead.begin(),vtBufRead.begin() + dwRead);  
  84.     }  
  85.     else  
  86.     {  
  87.      DWORD dwCover = g_dwLenReadBuf + dwRead - g_vtBufRead.size();  
  88.      std::copy(g_vtBufRead.begin() + dwCover,g_vtBufRead.begin() + g_dwLenReadBuf,g_vtBufRead.begin());  
  89.      std::copy(vtBufRead.begin(),vtBufRead.begin() + dwRead,g_vtBufRead.begin() + (g_dwLenReadBuf - dwCover));  
  90.      g_dwLenReadBuf = g_vtBufRead.size();  
  91.     }  
  92.    }  
  93.      
  94.    g_bReaded = FALSE;  
  95.      
  96.    DEBUGMSG(TRUE,(TEXT("[VSP]:Read data : %d/r/n"),dwRead));   
  97.     
  98.    LeaveCriticalSection(&g_csRead);  
  99.   }  
  100.    
  101.   if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 || dwRead == 0))  
  102.   {  
  103.    //The return event mask is only EV_RXCHAR and there is not EV_RXCHAR in the wait mask.  
  104.    continue;  
  105.   }  
  106.    
  107.   InterlockedExchange(reinterpret_cast<LONG *>(&g_dwEvtMask),dwEvtMask);  
  108.   PulseEvent(g_hEventComm);    
  109.     
  110.   //Sleep for other thread to respond to the event  
  111.   Sleep(100);  
  112.     
  113.   DEBUGMSG(TRUE,(TEXT("[VSP]:PulseEvent! The event-mask is 0x%x/r/n"),dwEvtMask));   
  114.     
  115.  }  
  116.    
  117.  RETAILMSG(TRUE,(TEXT("[VSP]:Exit the MonitorCommEventProc/r/n")));   
  118.  InterlockedExchange(reinterpret_cast<LONG *>(&g_bMonitorProcRunning),FALSE);  
  119.    
  120.  return 0;  
  121. }  
  122.   
  123. BOOL VSP_Close(DWORD dwHandle)  
  124. {  
  125.  EnterCriticalSection(&g_csOpen);  
  126.    
  127.  g_uiOpenCount --;   
  128.  if(g_uiOpenCount == 0)  
  129.  {    
  130.   //Notify the monitor thread to exit.   
  131.   InterlockedExchange(reinterpret_cast<LONG *>(&g_bExitMonitorProc),TRUE);  
  132.   DWORD dwMask = 0;  
  133.   GetCommMask(g_hCom,&dwMask);  
  134.   SetCommMask(g_hCom,dwMask);    
  135.     
  136.   while(InterlockedExchange(reinterpret_cast<LONG *>(&g_bMonitorProcRunning),TRUE) == TRUE)  
  137.   {  
  138.    Sleep(20);  
  139.   }  
  140.   InterlockedExchange(reinterpret_cast<LONG *>(&g_bMonitorProcRunning),FALSE);  
  141.     
  142.   CloseHandle(g_hCom);  
  143.   g_hCom = NULL;  
  144.  }  
  145.   
  146.  LeaveCriticalSection(&g_csOpen);  
  147.    
  148.  return TRUE;  
  149. }  
  150.   
  151. DWORD VSP_Init(DWORD dwContext)  
  152. {  
  153.  RETAILMSG(TRUE,(TEXT("[+VSP_Init]/r/n")));   
  154.    
  155.  InitializeCriticalSection(&g_csOpen);  
  156.  InitializeCriticalSection(&g_csRead);  
  157.  InitializeCriticalSection(&g_csWrite);  
  158.    
  159.  g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);  
  160.     
  161.  RETAILMSG(TRUE,(TEXT("[-VSP_Init]/r/n")));  
  162.     
  163.  return TRUE;  
  164. }  
  165.   
  166. BOOL VSP_Deinit(  
  167.     DWORD dwContext     // future: pointer to the per disk structure  
  168.     )  
  169. {  
  170.  RETAILMSG(TRUE,(TEXT("[+VSP_Deinit]/r/n")));   
  171.    
  172.  CloseHandle(g_hEventComm);  
  173.  g_hEventComm = NULL;  
  174.    
  175.  DeleteCriticalSection(&g_csOpen);  
  176.  DeleteCriticalSection(&g_csRead);  
  177.  DeleteCriticalSection(&g_csWrite);  
  178.     
  179.  RETAILMSG(TRUE,(TEXT("[-VSP_Deinit]/r/n")));   
  180.  return TRUE;  
  181. }  
  182.   
  183. DWORD VSP_Open(  
  184.     DWORD dwData,  
  185.     DWORD dwAccess,  
  186.     DWORD dwShareMode  
  187.     )  
  188. {  
  189.  BOOL bResult = FALSE;  
  190.    
  191.  EnterCriticalSection(&g_csOpen);  
  192.    
  193.  //The variable  
  194.  CReg reg;  
  195.  std::vector<TCHAR> vtBuf(MAX_PATH,0);  
  196.  COMMPROP commProp = {0};  
  197.    
  198.  if(g_uiOpenCount != 0)  
  199.  {    
  200.   goto SET_SUCCEED_FLAG;  
  201.  }   
  202.    
  203.  if(reg.Open(REG_ROOT_KEY,REG_DEVICE_SUB_KEY) == FALSE)  
  204.  {  
  205.   RETAILMSG(TRUE,(TEXT("[VSP]:Failed to open the registry/r/n")));  
  206.   goto LEAVE_CRITICAL_SECTION;  
  207.  }  
  208.    
  209.  //Get the MAP_PORT name   
  210.  reg.GetValueSZ(REG_MAP_PORT_NAME,&vtBuf[0],vtBuf.size());  
  211.     
  212.  g_hCom = CreateFile(&vtBuf[0],GENERIC_READ | GENERIC_WRITE ,0,NULL,OPEN_EXISTING,0,NULL);  
  213.  if(g_hCom == INVALID_HANDLE_VALUE )  
  214.  {  
  215.   RETAILMSG(TRUE,(TEXT("[VSP]Failed to map to %s/r/n"),&vtBuf[0]));  
  216.   goto LEAVE_CRITICAL_SECTION;  
  217.  }  
  218.  else  
  219.  {  
  220.   RETAILMSG(TRUE,(TEXT("[VSP]Succeed to map to %s/r/n"),&vtBuf[0]));  
  221.  }   
  222.    
  223.  InterlockedExchange(reinterpret_cast<LONG *>(&g_bExitMonitorProc),FALSE);  
  224.  CloseHandle(CreateThread(NULL,NULL,MonitorCommEventProc,NULL,NULL,NULL));  
  225.    
  226. SET_SUCCEED_FLAG:  
  227.    
  228.  g_uiOpenCount ++;  
  229.  bResult = TRUE;  
  230.    
  231. LEAVE_CRITICAL_SECTION:   
  232.    
  233.  LeaveCriticalSection(&g_csOpen);  
  234.    
  235.  return bResult;  
  236. }  
  237.   
  238.   
  239. BOOL VSP_IOControl(  
  240.     DWORD dwHandle,  
  241.     DWORD dwIoControlCode,  
  242.     PBYTE pBufIn,  
  243.     DWORD dwBufInSize,  
  244.     PBYTE pBufOut,  
  245.     DWORD dwBufOutSize,  
  246.     PDWORD pBytesReturned  
  247.     )  
  248. {   
  249.  switch(dwIoControlCode)  
  250.  {  
  251.   case IOCTL_SERIAL_SET_DCB:  
  252.   {     
  253.    return SetCommState(g_hCom,reinterpret_cast<DCB *>(pBufIn));  
  254.   }  
  255.   case IOCTL_SERIAL_GET_DCB:  
  256.   {     
  257.    return GetCommState(g_hCom,reinterpret_cast<DCB *>(pBufOut));  
  258.   }  
  259.   case IOCTL_SERIAL_WAIT_ON_MASK:  
  260.   {      
  261.    if(dwBufOutSize < sizeof(DWORD) ||  WaitForSingleObject(g_hEventComm,INFINITE) == WAIT_TIMEOUT)  
  262.    {  
  263.     *pBytesReturned = 0;     
  264.     return FALSE;  
  265.    }  
  266.    else  
  267.    {  
  268.     InterlockedExchange(reinterpret_cast<LONG *>(pBufOut),g_dwEvtMask);  
  269.     *pBytesReturned = sizeof(DWORD);        
  270.     return TRUE;  
  271.    }       
  272.   }  
  273.   case IOCTL_SERIAL_SET_WAIT_MASK:  
  274.   {    
  275.    g_dwWaitMask = *reinterpret_cast<DWORD *>(pBufIn);  
  276.    return SetCommMask(g_hCom,g_dwWaitMask | EV_RXCHAR); //The driver need the EV_RXCHAR notify event.  
  277.   }  
  278.   case IOCTL_SERIAL_GET_WAIT_MASK:  
  279.   {     
  280.    if(dwBufOutSize < sizeof(DWORD) || GetCommMask(g_hCom,reinterpret_cast<DWORD *>(pBufOut)) == FALSE)  
  281.    {  
  282.     *pBytesReturned = 0;     
  283.     return FALSE;  
  284.    }  
  285.    else  
  286.    {  
  287.     *pBytesReturned = sizeof(DWORD);  
  288.     return TRUE;  
  289.    }  
  290.   }  
  291.  }  
  292.    
  293.  return FALSE;  
  294. }  
  295.   
  296. DWORD VSP_Read(DWORD dwHandle, LPVOID pBuffer, DWORD dwNumBytes)  
  297. {  
  298.  EnterCriticalSection(&g_csRead);    
  299.    
  300.  //The g_dwLenReadBuf must be less than or equal to g_vtBufRead.size(), so needn't compare with each other.  
  301.  DWORD dwCopy = g_dwLenReadBuf > dwNumBytes ? dwNumBytes : g_dwLenReadBuf;  
  302.  if(dwCopy != 0)  
  303.  {  
  304.   memcpy(pBuffer,&g_vtBufRead[0],dwCopy);  
  305.  }    
  306.  DEBUGMSG(TRUE,(TEXT("[VSP]:Copy cout:%d/r/n"),dwCopy));  
  307.   
  308.  g_bReaded = TRUE;  
  309.    
  310.  LeaveCriticalSection(&g_csRead);  
  311.    
  312.  //Sleep for other thread to entry the function.  
  313.  Sleep(10);   
  314.    
  315.    
  316.  return dwCopy;  
  317. }  
  318.   
  319. DWORD VSP_Write(DWORD dwHandle, LPCVOID pBuffer, DWORD dwNumBytes)  
  320. {  
  321.  EnterCriticalSection(&g_csWrite);  
  322.  DWORD dwWrite = 0;  
  323.  WriteFile(g_hCom,pBuffer,dwNumBytes,&dwWrite,NULL);  
  324.  LeaveCriticalSection(&g_csWrite);  
  325.  return dwWrite;  
  326. }  
  327.   
  328.   
  329. DWORD VSP_Seek(DWORD dwHandle, long lDistance, DWORD dwMoveMethod)  
  330. {  
  331.  return FALSE;  
  332. }  
  333.   
  334. void VSP_PowerUp(void)  
  335. {  
  336.  return;  
  337. }  
  338.   
  339. void VSP_PowerDown(void)  
  340. {  
  341.  return;  
  342. }  

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







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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值