SerialPort.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. ///////////////////////////////// Includes ////////////////////////////////////
  2. #include "stdafx.h"
  3. #include "serialport.h"
  4. #ifndef _WINERROR
  5. #pragma message("To avoid this message, please put WinError.h in your pre compiled header")
  6. #include <WinError.h>
  7. #endif
  8. ///////////////////////////////// Defines /////////////////////////////////////
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #endif
  12. //////////////////////////////// Implementation ///////////////////////////////
  13. CSerialException::CSerialException(DWORD dwError) : m_dwError(dwError)
  14. {
  15. }
  16. BOOL CSerialException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError, PUINT pnHelpContext /* = 0 */)
  17. {
  18. // Validate our parameters
  19. ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError));
  20. if(pnHelpContext != NULL)
  21. *pnHelpContext = 0;
  22. // What will be the return value from this function(assume the worst)
  23. BOOL bSuccess = FALSE;
  24. LPTSTR lpBuffer;
  25. DWORD dwReturn = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  26. NULL,
  27. m_dwError,
  28. MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  29. reinterpret_cast<LPTSTR>(&lpBuffer),
  30. 0,
  31. NULL
  32. );
  33. if(dwReturn == 0)
  34. {
  35. *lpszError = _T('\0');
  36. }
  37. else
  38. {
  39. bSuccess = TRUE;
  40. Checked::tcsncpy_s(lpszError, nMaxError, lpBuffer, _TRUNCATE);
  41. LocalFree(lpBuffer);
  42. }
  43. return bSuccess;
  44. }
  45. CString CSerialException::GetErrorMessage()
  46. {
  47. CString strVal;
  48. LPTSTR pstrError = strVal.GetBuffer(ERR_BUFFER);
  49. GetErrorMessage(pstrError, ERR_BUFFER, NULL);
  50. strVal.ReleaseBuffer();
  51. return strVal;
  52. }
  53. IMPLEMENT_DYNAMIC(CSerialException, CException)
  54. #ifdef _DEBUG
  55. void CSerialException::Dump(CDumpContext &dc) const
  56. {
  57. CObject::Dump(dc);
  58. dc << _T("m_dwError = ") << m_dwError << _T("\n");
  59. }
  60. #endif
  61. CSerialPort::CSerialPort() : m_hComm(INVALID_HANDLE_VALUE), m_hEvent(NULL)
  62. {
  63. m_hKernel32 = GetModuleHandle(_T("KERNEL32.DLL"));
  64. if(m_hKernel32)
  65. m_lpfnCancelIO = reinterpret_cast<LPCANCELIO>(GetProcAddress(m_hKernel32, "CancelIo"));
  66. else
  67. m_lpfnCancelIO = NULL;
  68. }
  69. CSerialPort::~CSerialPort()
  70. {
  71. Close();
  72. }
  73. void CSerialPort::ThrowSerialException(DWORD dwError /* = 0 */)
  74. {
  75. if(dwError == 0)
  76. dwError = GetLastError();
  77. CSerialException* pException = new CSerialException(dwError);
  78. TRACE(_T("Warning: throwing CSerialException for error %d\n"), dwError);
  79. THROW(pException);
  80. }
  81. #ifdef _DEBUG
  82. void CSerialPort::Dump(CDumpContext &dc) const
  83. {
  84. dc << _T("m_hComm = ") << m_hComm << _T("\n");
  85. }
  86. #endif
  87. void CSerialPort::Open(LPCTSTR pszPort, /* COM1 */
  88. DWORD dwBaud /* = 9600 */,
  89. Parity parity /* = NoParity */,
  90. BYTE dataBits /* = 8 */,
  91. StopBits stopBits /* = OneStopBit */,
  92. FlowControl flowCtl /* = NoFlowControl */,
  93. BOOL bOverlapped /* = 0 */)
  94. {
  95. Close(); // In case we are already open
  96. // Call CreateFile to open the comms port
  97. TCHAR szPort[16] = {0};
  98. _stprintf_s(szPort, _T("\\\\.\\%s"), pszPort);
  99. m_hComm = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, bOverlapped ? FILE_FLAG_OVERLAPPED : 0, NULL);
  100. if(m_hComm == INVALID_HANDLE_VALUE)
  101. {
  102. DWORD dwLastError = GetLastError();
  103. //LOG4C((LOG_WARN,"%s打开失败,GetLastError=%ld", szPort, dwLastError));
  104. //Global::WriteReportLog(1, "Serial port error", "Open Serial Port Fail, GetLastError=%ld !", dwLastError);
  105. return;
  106. }
  107. // Create the event we need for later synchronisation use
  108. m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  109. if(m_hEvent == NULL)
  110. {
  111. DWORD dwLastError = GetLastError();
  112. //LOG4C((LOG_WARN,"CreateEvent失败,GetLastError=%ld", szPort, dwLastError));
  113. //Global::WriteReportLog(1, "Serial port error", "CreateEvent Fail, GetLastError=%ld !", dwLastError);
  114. Close();
  115. return;
  116. }
  117. if ( !SetupComm(m_hComm,10240,2048) )
  118. {
  119. DWORD dwLastError = GetLastError();
  120. CloseHandle(m_hComm);
  121. CloseHandle(m_hEvent);
  122. // Global::WriteReportLog(1, "Serial port error", "SetupComm Fail, GetLastError=%ld !", dwLastError);
  123. Close();
  124. return ;
  125. }
  126. // Get the current state prior to changing it
  127. DCB dcb;
  128. dcb.DCBlength = sizeof(DCB);
  129. GetState(dcb);
  130. // Setup the baud rate
  131. dcb.BaudRate = dwBaud;
  132. // Setup the Parity
  133. switch(parity)
  134. {
  135. case NoParity:
  136. dcb.Parity = NOPARITY;
  137. break;
  138. case OddParity:
  139. dcb.Parity = ODDPARITY;
  140. break;
  141. case EvenParity:
  142. dcb.Parity = EVENPARITY;
  143. break;
  144. case MarkParity:
  145. dcb.Parity = MARKPARITY;
  146. break;
  147. case SpaceParity:
  148. dcb.Parity = SPACEPARITY;
  149. break;
  150. default:
  151. ASSERT(FALSE);
  152. break;
  153. }
  154. // Setup the data bits
  155. dcb.ByteSize = dataBits;
  156. // Setup the stop bits
  157. switch(stopBits)
  158. {
  159. case OneStopBit:
  160. dcb.StopBits = ONESTOPBIT;
  161. break;
  162. case OnePointFiveStopBits:
  163. dcb.StopBits = ONE5STOPBITS;
  164. break;
  165. case TwoStopBits:
  166. dcb.StopBits = TWOSTOPBITS;
  167. break;
  168. default:
  169. ASSERT(FALSE);
  170. break;
  171. }
  172. // Setup the flow control
  173. dcb.fDsrSensitivity = FALSE;
  174. switch(flowCtl)
  175. {
  176. case NoFlowControl:
  177. dcb.fOutxCtsFlow = FALSE;
  178. dcb.fOutxDsrFlow = FALSE;
  179. dcb.fOutX = FALSE;
  180. dcb.fInX = FALSE;
  181. break;
  182. case CtsRtsFlowControl:
  183. dcb.fOutxCtsFlow = TRUE;
  184. dcb.fOutxDsrFlow = FALSE;
  185. dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  186. dcb.fOutX = FALSE;
  187. dcb.fInX = FALSE;
  188. break;
  189. case CtsDtrFlowControl:
  190. dcb.fOutxCtsFlow = TRUE;
  191. dcb.fOutxDsrFlow = FALSE;
  192. dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
  193. dcb.fOutX = FALSE;
  194. dcb.fInX = FALSE;
  195. break;
  196. case DsrRtsFlowControl:
  197. dcb.fOutxCtsFlow = FALSE;
  198. dcb.fOutxDsrFlow = TRUE;
  199. dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
  200. dcb.fOutX = FALSE;
  201. dcb.fInX = FALSE;
  202. break;
  203. case DsrDtrFlowControl:
  204. dcb.fOutxCtsFlow = FALSE;
  205. dcb.fOutxDsrFlow = TRUE;
  206. dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
  207. dcb.fOutX = FALSE;
  208. dcb.fInX = FALSE;
  209. break;
  210. case XonXoffFlowControl:
  211. dcb.fOutxCtsFlow = FALSE;
  212. dcb.fOutxDsrFlow = FALSE;
  213. dcb.fOutX = TRUE;
  214. dcb.fInX = TRUE;
  215. dcb.XonChar = 0x11;
  216. dcb.XoffChar = 0x13;
  217. dcb.XoffLim = 100;
  218. dcb.XonLim = 100;
  219. break;
  220. default:
  221. ASSERT(FALSE);
  222. break;
  223. }
  224. //Now that we have all the settings in place, make the changes
  225. SetState(dcb);
  226. }
  227. void CSerialPort::Open(int nPort,
  228. DWORD dwBaud /* = 9600 */,
  229. Parity parity /* = NoParity */,
  230. BYTE dataBits /* = 8 */,
  231. StopBits stopBits /* = OneStopBit */,
  232. FlowControl flowCtl /* = NoFlowControl */,
  233. BOOL bOverlapped /* = 0 */)
  234. {
  235. //Form the string version of the port number
  236. CString strPort;
  237. strPort.Format(_T("\\\\.\\COM%d"), nPort);
  238. //Then delegate the work to the other version of Open
  239. Open(strPort, dwBaud, parity, dataBits, stopBits, flowCtl, bOverlapped);
  240. }
  241. void CSerialPort::Close()
  242. {
  243. if(IsOpen())
  244. {
  245. // Close down the comms port
  246. BOOL bSuccess = CloseHandle(m_hComm);
  247. m_hComm = INVALID_HANDLE_VALUE;
  248. if(!bSuccess)
  249. TRACE(_T("CSerialPort::Close, Failed to close up the comms port, Error:%d\n"), GetLastError());
  250. // LOG4C((LOG_WARN,"关闭串口失败,GetLastError=%ld", GetLastError()));
  251. // Free the event object we are using
  252. if(m_hEvent)
  253. {
  254. CloseHandle(m_hEvent);
  255. m_hEvent = NULL;
  256. }
  257. }
  258. }
  259. void CSerialPort::Attach(HANDLE hComm)
  260. {
  261. Close();
  262. //Validate our parameters, now that the port has been closed
  263. ASSERT(m_hComm == INVALID_HANDLE_VALUE);
  264. ASSERT(m_hEvent == NULL);
  265. m_hComm = hComm;
  266. //Create the event we need for later synchronisation use
  267. m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  268. if (m_hEvent == NULL)
  269. {
  270. DWORD dwLastError = GetLastError();
  271. Close();
  272. //TRACE(_T("CSerialPort::Attach, Failed in call to CreateEvent in Attach, Error:%d\n"), dwLastError);
  273. // LOG4C((LOG_WARN,"CreateEvent失败,GetLastError=%ld", GetLastError()));
  274. //ThrowSerialException(dwLastError);
  275. }
  276. }
  277. HANDLE CSerialPort::Detach()
  278. {
  279. // What will be the return value from this function
  280. HANDLE hVal = m_hComm;
  281. m_hComm = INVALID_HANDLE_VALUE;
  282. if(m_hEvent)
  283. {
  284. CloseHandle(m_hEvent);
  285. m_hEvent = NULL;
  286. }
  287. return hVal;
  288. }
  289. DWORD CSerialPort::Read(void *lpBuf, DWORD dwCount)
  290. {
  291. // Validate our parameters
  292. ASSERT(IsOpen());
  293. if (lpBuf == NULL || !::AfxIsValidAddress(lpBuf, dwCount, FALSE))
  294. {
  295. // LOG4C((LOG_WARN, "Read的缓存地址无效!"))
  296. return 0;
  297. }
  298. DWORD dwErrorFlags = 0;
  299. COMSTAT ComStat;
  300. ClearCommError(m_hComm, &dwErrorFlags, &ComStat);
  301. #if 1
  302. // 使用ClearCommError来读取缓存区接受到的字节时,
  303. // 可能受系统线程调试或硬件延时, cbInQue为空,
  304. // 这里要用while延时获取;
  305. DWORD dwTick = GetTickCount();
  306. DWORD dwLastLen = 0;
  307. //while (ComStat.cbInQue == 0)
  308. while(1)
  309. {// cbInQue表示输入缓冲区的字节数;
  310. Sleep(150);
  311. if (GetTickCount() - dwTick > 5000)
  312. break;
  313. ClearCommError(m_hComm, &dwErrorFlags, &ComStat);
  314. if ( ComStat.cbInQue != 0 && dwLastLen == ComStat.cbInQue )
  315. break;
  316. dwLastLen = ComStat.cbInQue;
  317. }
  318. if (ComStat.cbInQue == 0)
  319. {
  320. // 串口无数据返回;
  321. // LOG4C((LOG_ERROR, "1.5秒超时已过,读串口失败,缓存区无数据"));
  322. return 0;
  323. }
  324. #endif
  325. DWORD dwBytesRead = 0;
  326. if(!ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, NULL))
  327. {
  328. DWORD dwLastError = GetLastError();
  329. //TRACE(_T("CSerialPort::Read, Failed in call to ReadFile, Error:%d\n"), dwLastError);
  330. // LOG4C((LOG_WARN,"ReadFile失败,GetLastError=%ld", dwLastError));
  331. //ThrowSerialException(dwLastError);
  332. }
  333. return dwBytesRead;
  334. }
  335. void CSerialPort::Read(void *lpBuf, DWORD dwCount, OVERLAPPED &overlapped, DWORD *pBytesRead /* = 0 */)
  336. {
  337. // Validate our parameters
  338. ASSERT(IsOpen());
  339. DWORD dwBytesRead = 0;
  340. BOOL bSuccess = ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, &overlapped);
  341. if(!bSuccess)
  342. {
  343. DWORD dwLastError = GetLastError();
  344. //TRACE(_T("CSerialPort::Read, Failed in call to ReadFile, Error:%d\n"), dwLastError);
  345. // LOG4C((LOG_WARN,"ReadFile失败,GetLastError=%ld", dwLastError));
  346. //ThrowSerialException(dwLastError);
  347. }
  348. else
  349. {
  350. if(pBytesRead)
  351. *pBytesRead = dwBytesRead;
  352. }
  353. }
  354. DWORD CSerialPort::Write(const void *lpBuf, DWORD dwCount)
  355. {
  356. // Validate our parameters
  357. ASSERT(IsOpen());
  358. DWORD dwBytesWritten = 0;
  359. // 写前,清空缓存区;
  360. PurgeComm(m_hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  361. if(!WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, NULL))
  362. {
  363. DWORD dwLastError = GetLastError();
  364. //TRACE(_T("CSerialPort::Write, Failed in call to WriteFile, Error:%d\n"), dwLastError);
  365. // LOG4C((LOG_WARN,"WriteFile失败,GetLastError=%ld", dwLastError));
  366. //ThrowSerialException(dwLastError);
  367. }
  368. return dwBytesWritten;
  369. }
  370. void CSerialPort::Write(const void *lpBuf, DWORD dwCount, OVERLAPPED &overlapped, DWORD *pBytesWritten /* = 0 */)
  371. {
  372. // Validate our parameters
  373. ASSERT(IsOpen());
  374. DWORD dwBytesWritten = 0;
  375. // 写前,清空缓存区;
  376. PurgeComm(m_hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  377. BOOL bSuccess = WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, &overlapped);
  378. if(!bSuccess)
  379. {
  380. DWORD dwLastError = GetLastError();
  381. //TRACE(_T("CSerialPort::Write, Failed in call to WriteFile, Error:%d\n"), dwLastError);
  382. // LOG4C((LOG_WARN,"WriteFile失败,GetLastError=%ld", dwLastError));
  383. //ThrowSerialException(dwLastError);
  384. }
  385. else
  386. {
  387. if(pBytesWritten)
  388. *pBytesWritten = dwBytesWritten;
  389. }
  390. }
  391. void CSerialPort::GetOverlappedResult(OVERLAPPED &overlapped, DWORD &dwBytesTransferred, BOOL bWait)
  392. {
  393. // Validate our parameters
  394. ASSERT(IsOpen());
  395. if(!::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransferred, bWait))
  396. {
  397. DWORD dwLastError = GetLastError();
  398. //TRACE(_T("CSerialPort::GetOverlappedResult, Failed in call to GetOverlappedResult, Error:%d\n"), dwLastError);
  399. // LOG4C((LOG_WARN,"GetOverlappedResult失败,GetLastError=%ld", dwLastError));
  400. //ThrowSerialException(dwLastError);
  401. }
  402. }
  403. void CSerialPort::_OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped)
  404. {
  405. // Validate our parameters
  406. AFXASSUME(lpOverlapped);
  407. // Convert back to the C++ world
  408. CSerialPort* pSerialPort = static_cast<CSerialPort*>(lpOverlapped->hEvent);
  409. AFXASSUME(pSerialPort);
  410. // Call the C++ function
  411. pSerialPort->OnCompletion(dwErrorCode, dwCount, lpOverlapped);
  412. }
  413. void CSerialPort::OnCompletion(DWORD /* dwErrorCode */, DWORD /* dwCount */, LPOVERLAPPED lpOverlapped)
  414. {
  415. // Just free the memory which was previously allocated for the OVERLAPPED structure
  416. delete lpOverlapped;
  417. // Your derived classes can do something useful in OnCompletion, but don't forget to
  418. // call CSerialPort::OnCompletion to ensure the memory is freed
  419. }
  420. void CSerialPort::CancelIO()
  421. {
  422. // Validate our parameters
  423. ASSERT(IsOpen());
  424. if(m_lpfnCancelIO == NULL)
  425. {
  426. //TRACE(_T("CSerialPort::CancelIO, CancelIO function is not supported on this OS, You need to be running at least NT 4 or Win 98 to use this function\n"));
  427. // LOG4C((LOG_WARN,"CancelIO失败,m_lpfnCancelIO函数指针空"));
  428. //ThrowSerialException(ERROR_CALL_NOT_IMPLEMENTED);
  429. }
  430. if(!m_lpfnCancelIO(m_hComm))
  431. {
  432. DWORD dwLastError = GetLastError();
  433. //TRACE(_T("Failed in call to CancelIO, Error:%d\n"), dwLastError);
  434. // LOG4C((LOG_WARN,"CancelIO失败,GetLastError=%ld", dwLastError));
  435. //ThrowSerialException(dwLastError);
  436. }
  437. }
  438. DWORD CSerialPort::BytesWaiting()
  439. {
  440. // Validate our parameters
  441. ASSERT(IsOpen());
  442. // Check to see how many characters are unread
  443. COMSTAT stat;
  444. GetStatus(stat);
  445. return stat.cbInQue;
  446. }
  447. BOOL CSerialPort::DataWaiting(DWORD dwTimeout)
  448. {
  449. // Validate our parameters
  450. ASSERT(IsOpen());
  451. // Setup to wait fo incoming data
  452. DWORD dwOldMask;
  453. GetMask(dwOldMask);
  454. SetMask(EV_RXCHAR);
  455. // Setup the overlapped structure
  456. OVERLAPPED overlapped;
  457. overlapped.hEvent = m_hEvent;
  458. // Assume the worst
  459. BOOL bSuccess = FALSE;
  460. DWORD dwEvent;
  461. bSuccess = WaitEvent(dwEvent, overlapped);
  462. if(!bSuccess)
  463. {
  464. if(WaitForSingleObject(overlapped.hEvent, dwTimeout) == WAIT_OBJECT_0)
  465. {
  466. DWORD dwBytesTransferred;
  467. GetOverlappedResult(overlapped, dwBytesTransferred, FALSE);
  468. bSuccess = TRUE;
  469. }
  470. }
  471. // Reset the event mask
  472. SetMask(dwOldMask);
  473. return bSuccess;
  474. }
  475. void CSerialPort::WriteEx(const void *lpBuf, DWORD dwCount)
  476. {
  477. // Validate our parameters
  478. ASSERT(IsOpen());
  479. OVERLAPPED* pOverlapped = new OVERLAPPED;
  480. memset(pOverlapped, 0, sizeof(OVERLAPPED));
  481. pOverlapped->hEvent = static_cast<HANDLE>(this);
  482. if(!WriteFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion))
  483. {
  484. DWORD dwLastError = GetLastError();
  485. delete pOverlapped;
  486. //TRACE(_T("CSerialPort::WriteEx, Failed in call to WriteFileEx, Error:%d\n"), dwLastError);
  487. // LOG4C((LOG_WARN,"WriteEx失败,GetLastError=%ld", dwLastError));
  488. //ThrowSerialException(dwLastError);
  489. }
  490. }
  491. void CSerialPort::ReadEx(void *lpBuf, DWORD dwCount)
  492. {
  493. // Validate our parameters
  494. ASSERT(IsOpen());
  495. OVERLAPPED* pOverlapped = new OVERLAPPED;
  496. memset(pOverlapped, 0, sizeof(OVERLAPPED));
  497. pOverlapped->hEvent = static_cast<HANDLE>(this);
  498. if(!ReadFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion))
  499. {
  500. DWORD dwLastError = GetLastError();
  501. delete pOverlapped;
  502. //TRACE(_T("CSerialPort::ReadEx, Failed in call to ReadFileEx, Error:%d\n"), dwLastError);
  503. // LOG4C((LOG_WARN,"ReadEx失败,GetLastError=%ld", dwLastError));
  504. //ThrowSerialException(dwLastError);
  505. }
  506. }
  507. void CSerialPort::TransmitChar(char cChar)
  508. {
  509. // Validate our parameters
  510. ASSERT(IsOpen());
  511. if(!TransmitCommChar(m_hComm, cChar))
  512. {
  513. DWORD dwLastError = GetLastError();
  514. //TRACE(_T("CSerialPort::TransmitChar, Failed in call to TransmitCommChar, Error:%d\n"), dwLastError);
  515. // LOG4C((LOG_WARN,"TransmitCommChar失败,GetLastError=%ld", dwLastError));
  516. //ThrowSerialException(dwLastError);
  517. }
  518. }
  519. void CSerialPort::GetConfig(COMMCONFIG &config)
  520. {
  521. // Validate our parameters
  522. ASSERT(IsOpen());
  523. DWORD dwSize = sizeof(COMMCONFIG);
  524. if(!GetCommConfig(m_hComm, &config, &dwSize))
  525. {
  526. DWORD dwLastError = GetLastError();
  527. //TRACE(_T("CSerialPort::GetConfig, Failed in call to GetCommConfig, Error:%d\n"), dwLastError);
  528. // LOG4C((LOG_WARN,"GetCommConfig失败,GetLastError=%ld", dwLastError));
  529. //ThrowSerialException(dwLastError);
  530. }
  531. }
  532. void CSerialPort::SetConfig(COMMCONFIG &config)
  533. {
  534. // Validate our parameters
  535. ASSERT(IsOpen());
  536. DWORD dwSize = sizeof(COMMCONFIG);
  537. if(!SetCommConfig(m_hComm, &config, dwSize))
  538. {
  539. DWORD dwLastError = GetLastError();
  540. //TRACE(_T("CSerialPort::SetConfig, Failed in call to SetCommConfig, Error:%d\n"), dwLastError);
  541. // LOG4C((LOG_WARN,"SetCommConfig失败,GetLastError=%ld", dwLastError));
  542. //ThrowSerialException(dwLastError);
  543. }
  544. }
  545. void CSerialPort::SetBreak()
  546. {
  547. // Validate our parameters
  548. ASSERT(IsOpen());
  549. if(!SetCommBreak(m_hComm))
  550. {
  551. DWORD dwLastError = GetLastError();
  552. //TRACE(_T("CSerialPort::SetBreak, Failed in call to SetCommBreak, Error:%d\n"), dwLastError);
  553. // LOG4C((LOG_WARN,"SetCommBreak失败,GetLastError=%ld", dwLastError));
  554. //ThrowSerialException(dwLastError);
  555. }
  556. }
  557. void CSerialPort::ClearBreak()
  558. {
  559. // Validate our parameters
  560. ASSERT(IsOpen());
  561. if(!ClearCommBreak(m_hComm))
  562. {
  563. DWORD dwLastError = GetLastError();
  564. //TRACE(_T("CSerialPort::ClearBreak, Failed in call to ClearCommBreak, Error:%d\n"), dwLastError);
  565. // LOG4C((LOG_WARN,"ClearCommBreak失败,GetLastError=%ld", dwLastError));
  566. //ThrowSerialException(dwLastError);
  567. }
  568. }
  569. void CSerialPort::ClearError(DWORD &dwErrors)
  570. {
  571. // Validate our parameters
  572. ASSERT(IsOpen());
  573. if(!ClearCommError(m_hComm, &dwErrors, NULL))
  574. {
  575. DWORD dwLastError = GetLastError();
  576. //TRACE(_T("CSerialPort::ClearError, Failed in call to ClearCommError, Error:%d\n"), dwLastError);
  577. // LOG4C((LOG_WARN,"ClearCommError失败,GetLastError=%ld", dwLastError));
  578. //ThrowSerialException(dwLastError);
  579. }
  580. }
  581. void CSerialPort::GetDefaultConfig(int nPort, COMMCONFIG &config)
  582. {
  583. // Create the device name as a string
  584. CString strPort;
  585. strPort.Format(_T("COM%d"), nPort);
  586. DWORD dwSize = sizeof(COMMCONFIG);
  587. if(!GetDefaultCommConfig(strPort, &config, &dwSize))
  588. {
  589. DWORD dwLastError = GetLastError();
  590. //TRACE(_T("CSerialPort::GetDefaultConfig, Failed in call to GetDefaultCommConfig, Error:%d\n"), dwLastError);
  591. // LOG4C((LOG_WARN,"GetDefaultCommConfig失败,GetLastError=%ld", dwLastError));
  592. //ThrowSerialException(dwLastError);
  593. }
  594. }
  595. void CSerialPort::SetDefaultConfig(int nPort, COMMCONFIG &config)
  596. {
  597. // Create the device name as a string
  598. CString strPort;
  599. strPort.Format(_T("COM%d"), nPort);
  600. DWORD dwSize = sizeof(COMMCONFIG);
  601. if(!SetDefaultCommConfig(strPort, &config, dwSize))
  602. {
  603. DWORD dwLastError = GetLastError();
  604. //TRACE(_T("CSerialPort::SetDefaultConfig, Failed in call to SetDefaultCommConfig, Error:%d\n"), dwLastError);
  605. // LOG4C((LOG_WARN,"SetDefaultConfig失败,GetLastError=%ld", dwLastError));
  606. //ThrowSerialException(dwLastError);
  607. }
  608. }
  609. void CSerialPort::GetStatus(COMSTAT &stat)
  610. {
  611. // Validate our parameters
  612. ASSERT(IsOpen());
  613. DWORD dwErrors;
  614. if (!ClearCommError(m_hComm, &dwErrors, &stat))
  615. {
  616. DWORD dwLastError = GetLastError();
  617. //TRACE(_T("CSerialPort::GetStatus, Failed in call to ClearCommError, Error:%d\n"), dwLastError);
  618. // LOG4C((LOG_WARN,"ClearCommError失败,GetLastError=%ld", dwLastError));
  619. //ThrowSerialException(dwLastError);
  620. }
  621. }
  622. void CSerialPort::GetState(DCB &dcb)
  623. {
  624. //Validate our parameters
  625. ASSERT(IsOpen());
  626. if (!GetCommState(m_hComm, &dcb))
  627. {
  628. DWORD dwLastError = GetLastError();
  629. //TRACE(_T("CSerialPort::GetState, Failed in call to GetCommState, Error:%d\n"), dwLastError);
  630. // LOG4C((LOG_WARN,"GetCommState失败,GetLastError=%ld", dwLastError));
  631. //ThrowSerialException(dwLastError);
  632. }
  633. }
  634. void CSerialPort::SetState(DCB &dcb)
  635. {
  636. //Validate our parameters
  637. ASSERT(IsOpen());
  638. if (!SetCommState(m_hComm, &dcb))
  639. {
  640. DWORD dwLastError = GetLastError();
  641. //TRACE(_T("CSerialPort::SetState, Failed in call to SetCommState, Error:%d\n"), dwLastError);
  642. // LOG4C((LOG_WARN,"SetState失败,GetLastError=%ld", dwLastError));
  643. //ThrowSerialException(dwLastError);
  644. }
  645. }
  646. void CSerialPort::Escape(DWORD dwFunc)
  647. {
  648. //Validate our parameters
  649. ASSERT(IsOpen());
  650. if (!EscapeCommFunction(m_hComm, dwFunc))
  651. {
  652. DWORD dwLastError = GetLastError();
  653. //TRACE(_T("CSerialPort::Escape, Failed in call to EscapeCommFunction, Error:%d\n"), dwLastError);
  654. // LOG4C((LOG_WARN,"Escape失败,GetLastError=%ld", dwLastError));
  655. //ThrowSerialException(dwLastError);
  656. }
  657. }
  658. void CSerialPort::ClearDTR()
  659. {
  660. Escape(CLRDTR);
  661. }
  662. void CSerialPort::ClearRTS()
  663. {
  664. Escape(CLRRTS);
  665. }
  666. void CSerialPort::SetDTR()
  667. {
  668. Escape(SETDTR);
  669. }
  670. void CSerialPort::SetRTS()
  671. {
  672. Escape(SETRTS);
  673. }
  674. void CSerialPort::SetXOFF()
  675. {
  676. Escape(SETXOFF);
  677. }
  678. void CSerialPort::SetXON()
  679. {
  680. Escape(SETXON);
  681. }
  682. void CSerialPort::GetProperties(COMMPROP& properties)
  683. {
  684. //Validate our parameters
  685. ASSERT(IsOpen());
  686. if (!GetCommProperties(m_hComm, &properties))
  687. {
  688. DWORD dwLastError = GetLastError();
  689. //TRACE(_T("CSerialPort::GetProperties, Failed in call to GetCommProperties, Error:%d\n"), dwLastError);
  690. // LOG4C((LOG_WARN,"GetProperties失败,GetLastError=%ld", dwLastError));
  691. //ThrowSerialException(dwLastError);
  692. }
  693. }
  694. void CSerialPort::GetModemStatus(DWORD& dwModemStatus)
  695. {
  696. //Validate our parameters
  697. ASSERT(IsOpen());
  698. if (!GetCommModemStatus(m_hComm, &dwModemStatus))
  699. {
  700. DWORD dwLastError = GetLastError();
  701. //TRACE(_T("CSerialPort::GetModemStatus, Failed in call to GetCommModemStatus, Error:%d\n"), dwLastError);
  702. // LOG4C((LOG_WARN,"GetModemStatus失败,GetLastError=%ld", dwLastError));
  703. //ThrowSerialException(dwLastError);
  704. }
  705. }
  706. void CSerialPort::SetMask(DWORD dwMask)
  707. {
  708. //Validate our parameters
  709. ASSERT(IsOpen());
  710. if (!SetCommMask(m_hComm, dwMask))
  711. {
  712. DWORD dwLastError = GetLastError();
  713. //TRACE(_T("CSerialPort::SetMask, Failed in call to SetCommMask, Error:%d\n"), dwLastError);
  714. // LOG4C((LOG_WARN,"SetMask失败,GetLastError=%ld", dwLastError));
  715. //ThrowSerialException(dwLastError);
  716. }
  717. }
  718. void CSerialPort::GetMask(DWORD& dwMask)
  719. {
  720. //Validate our parameters
  721. ASSERT(IsOpen());
  722. if (!GetCommMask(m_hComm, &dwMask))
  723. {
  724. DWORD dwLastError = GetLastError();
  725. //TRACE(_T("CSerialPort::GetMask, Failed in call to GetCommMask, Error:%d\n"), dwLastError);
  726. // LOG4C((LOG_WARN,"GetMask失败,GetLastError=%ld", dwLastError));
  727. //ThrowSerialException(dwLastError);
  728. }
  729. }
  730. void CSerialPort::Flush()
  731. {
  732. //Validate our parameters
  733. ASSERT(IsOpen());
  734. if (!FlushFileBuffers(m_hComm))
  735. {
  736. DWORD dwLastError = GetLastError();
  737. //TRACE(_T("CSerialPort::Flush, Failed in call to FlushFileBuffers, Error:%d\n"), dwLastError);
  738. // LOG4C((LOG_WARN,"Flush失败,GetLastError=%ld", dwLastError));
  739. //ThrowSerialException(dwLastError);
  740. }
  741. }
  742. void CSerialPort::Purge(DWORD dwFlags)
  743. {
  744. //Validate our parameters
  745. ASSERT(IsOpen());
  746. if (!PurgeComm(m_hComm, dwFlags))
  747. {
  748. DWORD dwLastError = GetLastError();
  749. //TRACE(_T("CSerialPort::Purge, Failed in call to PurgeComm, Error:%d\n"), dwLastError);
  750. // LOG4C((LOG_WARN,"Purge失败,GetLastError=%ld", dwLastError));
  751. //ThrowSerialException(dwLastError);
  752. }
  753. }
  754. void CSerialPort::TerminateOutstandingWrites()
  755. {
  756. Purge(PURGE_TXABORT);
  757. }
  758. void CSerialPort::TerminateOutstandingReads()
  759. {
  760. Purge(PURGE_RXABORT);
  761. }
  762. void CSerialPort::ClearWriteBuffer()
  763. {
  764. Purge(PURGE_TXCLEAR);
  765. }
  766. void CSerialPort::ClearReadBuffer()
  767. {
  768. Purge(PURGE_RXCLEAR);
  769. }
  770. void CSerialPort::Setup(DWORD dwInQueue, DWORD dwOutQueue)
  771. {
  772. //Validate our parameters
  773. ASSERT(IsOpen());
  774. if (!SetupComm(m_hComm, dwInQueue, dwOutQueue))
  775. {
  776. DWORD dwLastError = GetLastError();
  777. //TRACE(_T("CSerialPort::Setup, Failed in call to SetupComm, Error:%d\n"), dwLastError);
  778. // LOG4C((LOG_WARN,"Setup失败,GetLastError=%ld", dwLastError));
  779. //ThrowSerialException(dwLastError);
  780. }
  781. }
  782. void CSerialPort::SetTimeouts(COMMTIMEOUTS& timeouts)
  783. {
  784. //Validate our parameters
  785. ASSERT(IsOpen());
  786. if (!SetCommTimeouts(m_hComm, &timeouts))
  787. {
  788. DWORD dwLastError = GetLastError();
  789. //TRACE(_T("CSerialPort::SetTimeouts, Failed in call to SetCommTimeouts, Error:%d\n"), dwLastError);
  790. // LOG4C((LOG_WARN,"SetTimeouts失败,GetLastError=%ld", dwLastError));
  791. //ThrowSerialException(dwLastError);
  792. }
  793. }
  794. void CSerialPort::GetTimeouts(COMMTIMEOUTS& timeouts)
  795. {
  796. //Validate our parameters
  797. ASSERT(IsOpen());
  798. if (!GetCommTimeouts(m_hComm, &timeouts))
  799. {
  800. DWORD dwLastError = GetLastError();
  801. //TRACE(_T("CSerialPort::GetTimeouts, Failed in call to GetCommTimeouts, Error:%d\n"), dwLastError);
  802. // LOG4C((LOG_WARN,"GetTimeouts失败,GetLastError=%ld", dwLastError));
  803. //ThrowSerialException(dwLastError);
  804. }
  805. }
  806. void CSerialPort::Set0Timeout()
  807. {
  808. COMMTIMEOUTS Timeouts;
  809. memset(&Timeouts, 0, sizeof(Timeouts));
  810. Timeouts.ReadIntervalTimeout = MAXDWORD;
  811. SetTimeouts(Timeouts);
  812. }
  813. void CSerialPort::Set0WriteTimeout()
  814. {
  815. COMMTIMEOUTS Timeouts;
  816. GetTimeouts(Timeouts);
  817. Timeouts.WriteTotalTimeoutMultiplier = 0;
  818. Timeouts.WriteTotalTimeoutConstant = 0;
  819. SetTimeouts(Timeouts);
  820. }
  821. void CSerialPort::Set0ReadTimeout()
  822. {
  823. COMMTIMEOUTS Timeouts;
  824. GetTimeouts(Timeouts);
  825. Timeouts.ReadIntervalTimeout = MAXDWORD;
  826. Timeouts.ReadTotalTimeoutMultiplier = 0;
  827. Timeouts.ReadTotalTimeoutConstant = 0;
  828. SetTimeouts(Timeouts);
  829. }
  830. void CSerialPort::WaitEvent(DWORD& dwMask)
  831. {
  832. //Validate our parameters
  833. ASSERT(IsOpen());
  834. if (!WaitCommEvent(m_hComm, &dwMask, NULL))
  835. {
  836. DWORD dwLastError = GetLastError();
  837. //TRACE(_T("CSerialPort::WaitEvent, Failed in call to WaitCommEvent, Error:%d\n"), dwLastError);
  838. // LOG4C((LOG_WARN,"WaitEvent失败,GetLastError=%ld", dwLastError));
  839. //ThrowSerialException(dwLastError);
  840. }
  841. }
  842. BOOL CSerialPort::WaitEvent(DWORD& dwMask, OVERLAPPED& overlapped)
  843. {
  844. //Validate our parameters
  845. ASSERT(IsOpen());
  846. ASSERT(overlapped.hEvent);
  847. BOOL bSuccess = WaitCommEvent(m_hComm, &dwMask, &overlapped);
  848. if (!bSuccess)
  849. {
  850. DWORD dwLastError = GetLastError();
  851. //TRACE(_T("CSerialPort::WaitEvent, Failed in call to WaitCommEvent, Error:%d\n"), dwLastError);
  852. // LOG4C((LOG_WARN,"WaitEvent失败,GetLastError=%ld", dwLastError));
  853. //ThrowSerialException(dwLastError);
  854. }
  855. return bSuccess;
  856. }