You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2154 lines
53 KiB
C

/*! \mainpage ComComm v1.51 <20><><EFBFBD>̴߳<DFB3><CCB4><EFBFBD>ͨѶ<CDA8><D1B6>
* \section About <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \n <EFBFBD>: ComComm v1.51
* \n <EFBFBD><EFBFBD>;: WINDOWS/WINCE <EFBFBD><EFBFBD><EFBFBD>̴߳<EFBFBD><EFBFBD><EFBFBD>ͨѶ<EFBFBD><EFBFBD>
* \n <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: C++ (ANSI/UNICODE)
* \n ƽ̨: WINDOWS(WIN98/NT/2000/XP/2003/Vista); WINCE 5.0 ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>; Pocket PC 2003 ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
* \n Ӳ<EFBFBD><EFBFBD>: PC<EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; USB<EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
* \n <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: BC++ 5(free tool); C++ BUILDER 4, 5, 6, X; EVC 4(sp4); G++ 3, 4; Intel C++ 7, 8, 9; VC++ 6(sp6), .NET, 2003, 2005;
* \n <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: llbird
* \n <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: wushaojian@21cn.com
* \n <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: http://blog.csdn.net/wujian53 http://www.cppblog.com/llbird
* \n ά<EFBFBD><EFBFBD>: 2002.10 - 2009.8
*
* \section Announce ˵<EFBFBD><EFBFBD>
* \n 1) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
* \n 2) <EFBFBD><EFBFBD><EFBFBD>Ƽ<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>, Ӧͨ<EFBFBD><EFBFBD>C++<EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
* \n 3) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>޸ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD>һ<EFBFBD>ݸ<EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ѷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸĶ<EFBFBD>;
* \n 4) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>cnComm1.4<EFBFBD><EFBFBD><EFBFBD>°, <EFBFBD>кܴ<EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD>ͬʱҲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ComComm;
* \n 5) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><EFBFBD>ϻ<EFBFBD>, ˮƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ComComm<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ;
*
* \section Log <EFBFBD><EFBFBD>־
* \n 2009 v1.51 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>ܲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٺʹ<EFBFBD><EFBFBD>ڴ򽻵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>;
* \n 2009 v1.5 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>÷ֿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>WINCE<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>(ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>);
* \n 2008 v1.4 <EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>ͬ<EFBFBD><EFBFBD>IO<EFBFBD>Ķ<EFBFBD><EFBFBD>߳<EFBFBD>֧<EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD><EFBFBD>C++<EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ComComm; Cn == C Next;
* \n 2007 v1.3 ϸ<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>޶<EFBFBD>;
* \n 2006 v1.2 ϸ<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>޶<EFBFBD>;
* \n 2005 v1.1 ϸ<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>޶<EFBFBD>;
* \n 2004 v1.0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>VC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>), <EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD>WINDOWƽ̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>, <EFBFBD>״ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>cnComm;
* \n 2002 v0.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨѶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>ͳC++<EFBFBD>ļ̳л<EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>ͳC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
*/
#ifndef COM_COMM_H
#pragma once
#define COM_COMM_H
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
//#include <windows.h>
#include <tchar.h>
#include <afxwin.h>
#if defined(UNDER_CE) && !defined(CN_COMM_FOR_CE)
#define CN_COMM_FOR_CE UNDER_CE //!< <20><><EFBFBD><EFBFBD>WINCE<43><45>֧<EFBFBD><D6A7>
#endif
#ifndef CN_COMM_FOR_CE
#include <mcx.h>
#include <process.h> // WINCEû<45><C3BB>process.h
#endif
#ifndef ON_COM_MSG_BASE
#define ON_COM_MSG_BASE WM_USER + 618 //!< <20><>Ϣ<EFBFBD><CFA2><EFBFBD>ŵĻ<C5B5><C4BB><EFBFBD>
#endif
// <20>͵<EFBFBD><CDB5><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ϣ WPARAM COM<4F>˿ں<CBBF>
#define ON_COM_RECEIVE ON_COM_MSG_BASE + 0 //!< EV_RXCHAR
#define ON_COM_RXCHAR ON_COM_MSG_BASE + 0 //!< EV_RXCHAR
#define ON_COM_CTS ON_COM_MSG_BASE + 1 //!< EV_CTS LPARAM==1 CTS ON
#define ON_COM_DSR ON_COM_MSG_BASE + 2 //!< EV_DSR LPARAM==1 DSR ON
#define ON_COM_RING ON_COM_MSG_BASE + 3 //!< EV_RING LPARAM==1 RING ON
#define ON_COM_RLSD ON_COM_MSG_BASE + 4 //!< EV_RLSD LPARAM==1 RLSD ON
#define ON_COM_BREAK ON_COM_MSG_BASE + 5 //!< EV_BREAK
#define ON_COM_TXEMPTY ON_COM_MSG_BASE + 6 //!< EV_TXEMPTY
#define ON_COM_ERROR ON_COM_MSG_BASE + 7 //!< EV_ERR LPARAM Error ID
#define ON_COM_RXFLAG ON_COM_MSG_BASE + 8 //!< EV_RXFLAG
#define ON_COM_POWER ON_COM_MSG_BASE + 9 //!< EV_POWER
#define ON_COM_EVENT1 ON_COM_MSG_BASE + 10//!< EV_EVENT1
#define ON_COM_EVENT2 ON_COM_MSG_BASE + 11//!< EV_EVENT2
#define ON_COM_RX80FULL ON_COM_MSG_BASE + 12//!< EV_RX80FULL
#define ON_COM_PERR ON_COM_MSG_BASE + 13//!< EV_PERR
#define ON_COM_CLOSE ON_COM_MSG_BASE + 14
#ifndef CN_COMM_WAIT_EVENT
#ifdef CN_COMM_FOR_CE
#define CN_COMM_WAIT_EVENT EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD | EV_POWER //!< WINCE Ĭ<>ϵĵȴ<C4B5><C8B4>¼<EFBFBD>| EV_RXFLAG
#else
#define CN_COMM_WAIT_EVENT EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD //!< WIN32 Ĭ<>ϵĵȴ<C4B5><C8B4>¼<EFBFBD>| EV_RXFLAG
#endif
#endif
#ifndef CN_COMM_BUFFER_MIN_BLOCK_SIZE
#define CN_COMM_BUFFER_MIN_BLOCK_SIZE 1024 //!< <20><><EFBFBD><EFBFBD><E5BBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сֵ
#endif
#if CN_COMM_BUFFER_MIN_BLOCK_SIZE < 4
#error CN_COMM_BUFFER_MIN_BLOCK_SIZE must >= 4 //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сֵ<D0A1><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>4
#endif
//#define CN_ASSERT(E) ((E) ? true: assert(E))
#ifndef CN_ASSERT
#define CN_2STR(L) _T(#L) //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<4C><D7AA><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
#define CN_LINE(L) CN_2STR(L) //!< <20><><EFBFBD>к<EFBFBD><4C><D7AA><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
/*! <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD>׳<EFBFBD><D7B3><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>԰潫<D4B0>˳<EFBFBD> <20><><EFBFBD>а<EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κδ<CEBA><CEB4><EFBFBD> */
//#define CN_ASSERT(E) ((E) ? true : ComComm::Assert(_T("CN_ASSERT(")_T(#E)_T(") failed; ComComm(")CN_LINE(__LINE__)_T("); ")))
#define CN_ASSERT(E) ((E) ? true : ComComm::Assert(_T("CN_ASSERT")))
#endif
//CN_COMM_STD_EXCEPTION CN_ASSERT <20><><EFBFBD>׳<EFBFBD><D7B3><EFBFBD>׼C++<2B>
#ifdef CN_COMM_STD_EXCEPTION
#include <stdexcept> //throw runtime_error(msg)
#endif
//CN_COMM_VCL_EXCEPTION CN_ASSERT <20><><EFBFBD>׳<EFBFBD>VCL<43>쳣(C++ Builder)
#if defined(CN_COMM_VCL_EXCEPTION) && defined(__BORLANDC__)
#include <vcl.h> //throw new Exception(msg)
#endif
//CN_COMM_MFC_EXCEPTION CN_ASSERT <20><><EFBFBD>׳<EFBFBD>MFC<46>쳣(VC++)
#ifdef CN_COMM_MFC_EXCEPTION
#include <Afx.h> //throw new MfcException(msg)
#endif
typedef void(__stdcall *ComCallback)(int nType, void *pThis);
class ComComm
{
public:
//! <20>ٽ<EFBFBD><D9BD><EFBFBD>
struct InnerLock;
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
class BlockBuffer;
//! MFC<46>
class MfcException;
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>ö<EFBFBD><C3B6>ֵ, 32λ<32><CEBB><EFBFBD><EFBFBD>
enum OptionEnum
{
EN_THREAD = 0x00000001, //!< <20><><EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD>߳<EFBFBD> <20><><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> WatchThread
EN_OVERLAPPED = 0x00000002, //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>IO<49><4F>ʽ
EN_RX_BUFFER = 0x00000004, //!< <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD>
EN_TX_BUFFER = 0x00000008, //!< <20><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
EN_RX_THREAD = 0x00000010, //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> <20><>ʱδ<CAB1><CEB4> ReadThread
EN_TX_THREAD = 0x00000020, //!< <20><><EFBFBD><EFBFBD>д<EFBFBD>߳<EFBFBD> <20><><EFBFBD><EFBFBD>WINCE<43><45>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ӧͬʱ<CDAC><CAB1><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> WriteThread
EN_SUSPEND = 0x00000040, //!< <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ʱ<EFBFBD><CAB1>ͣ
EN_ABOVE_NORMAL = 0x00000080, //!< <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
EN_FLUSH = 0x00000100, //!< <20><><EFBFBD>رմ<D8B1><D5B4><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28>˿ڻ<CBBF><DABB><EFBFBD><EFBFBD><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>
EN_FLUSH_ALL = 0x00000200 //!< ͬ<><CDAC>(<28><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>˿ڶ<CBBF><DAB6><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>дģ<D0B4><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>д<EFBFBD><D0B4> <20><><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD>̹߳<DFB3><CCB9><EFBFBD><EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD>
};
//! <20><><EFBFBD><EFBFBD><ECBAAF> <20><><EFBFBD>þ<EFBFBD><C3BE><EFBFBD>Ӧ<EFBFBD><D3A6>ģʽ \param[in] dwOption <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>OptionEnum<75><6D><EFBFBD>϶<EFBFBD><CFB6><EFBFBD>
#ifdef CN_COMM_FOR_CE
//! WINCE:Ĭ<>ϴ򿪴<CFB4><F2BFAAB4><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> <20><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> <20><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
ComComm(DWORD dwOption = EN_THREAD )
#else
//! WIN32:Ĭ<>ϴ򿪴<CFB4><F2BFAAB4><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> <20><EFBFBD>ص<EFBFBD><D8B5><EFBFBD>ʽ
ComComm(DWORD dwOption = EN_THREAD | EN_OVERLAPPED)
#endif
{
Init();
SetOption(dwOption);
}
//! <20><>һģʽ<C4A3><CABD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>cnComm1~1.3 \param[in] bThread <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> \param[in] bOverlapped <20><><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>I/O
ComComm(bool bThread, bool bOverlapped)
{
DWORD dwOption = 0;
if (bThread)
dwOption |= EN_THREAD;
if (bOverlapped)
dwOption |= EN_OVERLAPPED;
Init();
SetOption(dwOption);
}
//! <20><><EFBFBD><EFBFBD> <20>Զ<EFBFBD><D4B6>رմ<D8B1><D5B4><EFBFBD>
virtual ~ComComm()
{
Close();
Destroy();
}
//<2F><><EFBFBD>ûص<C3BB>
void SetDataCallBack(ComCallback pCb,void *pUser)
{
m_pComCb = pCb;
m_pUser = pUser;
}
//<2F><><EFBFBD>ûص<C3BB>
void SetDataCallBack(std::function<void()> _pfn)
{
m_pfn = _pfn;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB2BD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>ģʽ<C4A3>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>,<2C><><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD>Ĭ<EFBFBD><C4AC> <20>첽,<2C>첽ʱ<ECB2BD><CAB1><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ч
void SetWorkMode(BOOL bAsync,DWORD lReadTimeout=250)
{
m_lReadTimeout = lReadTimeout;
if (!bAsync)
{
DWORD dwOption = EN_THREAD;
SetOption(dwOption);
}
else
{
DWORD dwOption = EN_THREAD | EN_OVERLAPPED;
SetOption(dwOption);
}
}
//! <20>жϴ<D0B6><CFB4><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD>
bool IsOpen()
{
return hComm_ != INVALID_HANDLE_VALUE;
}
//! <20>жϴ<D0B6><CFB4><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD>
operator bool ()
{
return hComm_ != INVALID_HANDLE_VALUE;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ھ<EFBFBD><DABE><EFBFBD>
HANDLE GetHandle()
{
return hComm_;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ھ<EFBFBD><DABE><EFBFBD>
operator HANDLE()
{
return hComm_;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD GetPort()
{
return dwPort_;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>ȫ<EFBFBD><C8AB>
LPCTSTR GetPortName()
{
return szName_;
}
//! <20><><EFBFBD><EFBFBD>ComComm<6D>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD> <20><><EFBFBD><EFBFBD>32λ<32><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD GetOption()
{
return dwOption_;
}
//! <20><><EFBFBD><EFBFBD>ComComm<6D>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD> <20>ڴ򿪴<DAB4><F2BFAAB4><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[in] dwOption 32λ<32><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void SetOption(DWORD dwOption)
{
CN_ASSERT(!IsOpen());//! <20><><EFBFBD><EFBFBD>״̬<D7B4>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
dwOption_ = dwOption;
#ifdef CN_COMM_FOR_CE
CN_ASSERT(!IsOverlappedMode()); //! WINCE<43><45><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ص<EFBFBD>IO <20><>EN_OVERLAPPED<45><44><EFBFBD><EFBFBD>
dwOption_ &= (~EN_OVERLAPPED);
#endif
}
//! <20>޸<EFBFBD>ComComm<6D>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD> <20>ڴ򿪴<DAB4><F2BFAAB4><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[in] dwRemove ɾ<><C9BE><EFBFBD><EFBFBD>32λ<32><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[in] dwAdd <20><><EFBFBD>ӵ<EFBFBD>32λ<32><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ModifyOption(DWORD dwRemove, DWORD dwAdd)
{
CN_ASSERT(!IsOpen());//! <20><><EFBFBD><EFBFBD>״̬<D7B4>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
dwOption_ &= ~dwRemove;
dwOption_ |= dwAdd;
#ifdef CN_COMM_FOR_CE
CN_ASSERT(!IsOverlappedMode()); //! WINCE<43><45><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ص<EFBFBD>IO <20><>EN_OVERLAPPED<45><44><EFBFBD><EFBFBD>
dwOption_ &= (~EN_OVERLAPPED);
#endif
}
//! <20>Ƿ<EFBFBD><C7B7>ص<EFBFBD>IOģʽ
bool IsOverlappedMode()
{
return dwOption_ & EN_OVERLAPPED ? true : false;
}
//! <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
bool IsTxBufferMode()
{
return dwOption_ & EN_TX_BUFFER ? true : false;
}
//! <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EBBBBA><EFBFBD><EFBFBD>ģʽ
bool IsRxBufferMode()
{
return dwOption_ & EN_RX_BUFFER ? true : false;
}
//! <20><EFBFBD><E8B6A8><EFBFBD><EFBFBD>֪ͨ, <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>Сֵ
void SetNotifyNum(DWORD dwNum)
{
dwNotifyNum_ = dwNum;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD>߳̾<DFB3><CCBE><EFBFBD> \param[in] iOption EN_THREAD<41><44><EFBFBD><EFBFBD>hWatchThread_ EN_RX_THREAD<41><44><EFBFBD><EFBFBD>hReadThread_ EN_TX_THREAD<41><44><EFBFBD><EFBFBD>hWriteThread_ \return HANDLE <20>߳̾<DFB3><CCBE><EFBFBD>
HANDLE GetThread(int iOption = EN_THREAD)
{
return iOption == EN_THREAD ? hWatchThread_ : ((iOption == EN_RX_THREAD) ? hReadThread_ : hWriteThread_);
}
//! <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ӵ<EFBFBD><D3B5>¼<EFBFBD><C2BC><EFBFBD> <20><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч
void SetWaitEvent(DWORD dwEvent = CN_COMM_WAIT_EVENT)
{
CN_ASSERT(!IsOpen());///<2F><><EFBFBD><EFBFBD>״̬<D7B4>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
dwWaitEvent_ = dwEvent;
}
//! <20><><EFBFBD><EFBFBD><EBBBBA><EFBFBD><EFBFBD>
BlockBuffer& Input()
{
return I_;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BlockBuffer& Output()
{
return O_;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD> \param[in] bInput Ϊtrue<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><C4AC>Ϊtrue <20>ص<EFBFBD>IO<49><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD>ȷ<EFBFBD><C8B7> <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3>̨<EFBFBD><CCA8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>
DWORD GetCounter(bool bInput = true)
{
return bInput ? dwInCount_ : dwOutCount_;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ResetCounter()
{
dwInCount_ = dwOutCount_ = 0;
}
//! <20>򿪴<EFBFBD><F2BFAAB4><EFBFBD> <20><>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>cnComm1~1.3<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> cnComm1~1.3<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>9600, n, 8, 1<><31><EFBFBD>ö˿<C3B6> <20><>1.5<EFBFBD><EFBFBD>ֻ<EFBFBD>򿪶˿ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵȲ<EFBFBD><EFBFBD><EFBFBD> \param[in] dwPort <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1~1024
bool Open(DWORD dwPort)
{
if (!CN_ASSERT(dwPort>=1 && dwPort<=1024))
return false;
BindPort(dwPort);
if(!CN_ASSERT(OpenPort()))
return false;
if(!CN_ASSERT(SetupPort()))
return Close(), false;
if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
return Close(), false;
return true;
}
/*! \param[in] dwPort <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1~1024 \param[in] dwBaudRate <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[in] btParity <20><>żУ<C5BC><D0A3> \param[in] btByteSize <20><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB> \param[in] btStopBits ֹͣλ<D6B9><CEBB> */
//! <20>򿪴<EFBFBD><F2BFAAB4><EFBFBD> ȱʡ 9600, n, 8, 1 \sa bool Open(DWORD dwPort, LPCTSTR szSetStr)
bool Open(DWORD dwPort, DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT)
{
if (!CN_ASSERT(dwPort>=1 && dwPort<=1024))
return false;
BindPort(dwPort);
if (!CN_ASSERT(OpenPort()))
return false;
if (!CN_ASSERT(SetState(dwBaudRate, btParity, btByteSize, btStopBits)))
return Close(), false;
if (!CN_ASSERT(SetupPort()))
return Close(), false;
if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
return Close(), false;
return true;
}
#ifndef CN_COMM_FOR_CE
/*! \param[in] dwPort <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1~1024 \param[in] szSetStr <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "BBBB,P,D,S" <20><>: "9600,N,8,1" "1200,O,7,2"
BBBBΪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PΪ<EFBFBD><EFBFBD>żУ<EFBFBD><EFBFBD>(E | M | N | O | S) DΪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>(4 ~ 8) SΪֹͣλ<EFBFBD><EFBFBD>(1 | 1.5 | 2)
\code Open(1, "9600,E,8,2"); \endcode \b <EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>WINCE, ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>д<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>WINCEӲ<EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>ֲ<EFBFBD>Կ<EFBFBD><EFBFBD>ܲ<EFBFBD><EFBFBD><EFBFBD>, <EFBFBD>ʴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
//! <20>򿪴<EFBFBD><F2BFAAB4><EFBFBD>, <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>
bool Open(DWORD dwPort, LPCTSTR szSetStr)
{
if (!CN_ASSERT(dwPort>=1 && dwPort<=1024))
return false;
BindPort(dwPort);
if (!CN_ASSERT(OpenPort()))
return false;
if (!CN_ASSERT(SetState(szSetStr)))
return Close(), false;
if (!CN_ASSERT(SetupPort()))
return Close(), false;
if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
return Close(), false;
return true;
}
#endif
/*! \param[in] dwPort <20><>ʱ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD>û<EFBFBD>о<EFBFBD><D0BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ֪ͨ<CDA8>б<EFBFBD><D0B1><EFBFBD><EFBFBD>˿ںţ<DABA>Ӧע<D3A6><EFBFBD><E2B2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿ں<CBBF><DABA>ظ<EFBFBD>
\param[in] szPortName Ϊָ<EFBFBD><EFBFBD><EFBFBD>Ķ˿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>WINDOWS<EFBFBD><EFBFBD>\\\\.\\COM1<EFBFBD><EFBFBD><EFBFBD><EFBFBD>WINCE<EFBFBD><EFBFBD>COM1: , <EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
\param[in] dwBaudRate <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[in] btParity <EFBFBD><EFBFBD>żУ<EFBFBD><EFBFBD> \param[in] btByteSize <EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD> \param[in] btStopBits ֹͣλ<EFBFBD><EFBFBD>
\code Open(9999, "COM3:", 2400); \endcode \code Open(1028, "COM3:", 9600, N, 7, ONESTOPBIT); \endcode */
//! ָ<><D6B8><EFBFBD>Ķ˿<C4B6><CBBF><EFBFBD><EFBFBD>ƴ򿪴<C6B4><F2BFAAB4><EFBFBD>
bool Open(DWORD dwPort, LPCTSTR szPortName, DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT)
{
if(!CN_ASSERT(_tcslen(szPortName) < 64 - 1))
return false;
_tcscpy_s(szName_, szPortName);
dwPort_ = dwPort;//<2F><><EFBFBD><EFBFBD>֪ͨ<CDA8><D6AA>Ϣ
if (!CN_ASSERT(OpenPort()))
return false;
if (!CN_ASSERT(SetState(dwBaudRate, btParity, btByteSize, btStopBits)))
return Close(), false;
if (!CN_ASSERT(SetupPort()))
return Close(), false;
if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
return Close(), false;
return true;
}
//! ֱ<>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD> \param[out] pBuffer Ŀ<><EFBFBD><EABBBA><EFBFBD><EFBFBD> \param[in] dwLength <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> \param[in] dwWaitTime <20>ȴ<EFBFBD>ʱ<EFBFBD><CAB1><><C4AC>INFINITE) \return <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
DWORD ReadPort(LPVOID pBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
{
if (!IsOpen())
{
return -1;
}
COMSTAT Stat;
DWORD dwError, dwReadResult = 0;
if(!CN_ASSERT(IsOpen()) || !dwLength)
return 0;
if(::ClearCommError(hComm_, &dwError, &Stat) && dwError > 0)
::PurgeComm(hComm_, PURGE_RXABORT);
#ifndef CN_COMM_FOR_CE
if (IsOverlappedMode())//! <20>ص<EFBFBD>I/O<><4F> dwWaitTime==INFINITE <20><><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ɳ<EFBFBD>ʱ<EFBFBD><EFBFBD><E1B9B9><EFBFBD><EFBFBD> Ĭ<><C4AC><EFBFBD>趨0.5<EFBFBD><EFBFBD>
{
if (dwWaitTime == INFINITE)//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD> ֱ<>Ӷ<EFBFBD>ȡ<EFBFBD>˿ڽ<CBBF><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><E0B5B1>ԭ<EFBFBD><D4AD>1.3<EFBFBD>汾 Read(pBuffer, dwLength, false);
{
if (!::ReadFile(hComm_, pBuffer, dwLength, &dwReadResult, &RO_))
{//! <20>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>ComComm<6D>Ƽ<EFBFBD>ʹ<EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dwWaitTimeָ<65><D6B8><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1>
if (CN_ASSERT(::GetLastError() == ERROR_IO_PENDING))
{
while (!CN_ASSERT(::GetOverlappedResult(hComm_, &RO_, &dwReadResult, TRUE)))
;
}
}
}
else//! <20>ص<EFBFBD>I/O<><4F> dwWaitTime!=INFINITE <20><><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>dwWaitTime<6D><65><EFBFBD><EFBFBD>
{ //! dwWaitTime = 0 <20><EFBFBD><E0B5B1>ԭ<EFBFBD><D4AD>1.3<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>
DWORD dwBegin = GetTickCount(), dwEnd, dwCost, uReadLength, uReadReturn;
uReadLength = Stat.cbInQue > dwLength ? dwLength : Stat.cbInQue;
CN_ASSERT(::ReadFile(hComm_, pBuffer, uReadLength, &uReadReturn, &RO_));
dwReadResult += uReadReturn;
do
{
if (!::ReadFile(hComm_, (LPBYTE)pBuffer + dwReadResult, 1, &uReadReturn, &RO_))
{
if (dwWaitTime > 5 && WaitForSingleObject(RO_.hEvent, dwWaitTime) == WAIT_OBJECT_0)
{
dwEnd = GetTickCount();
dwCost = dwEnd>=dwBegin ? dwEnd-dwBegin : DWORD(-1L)-dwBegin+dwEnd;
CN_ASSERT(::GetOverlappedResult(hComm_, &RO_, &uReadReturn, FALSE));
dwWaitTime = dwWaitTime > dwCost ? dwWaitTime-dwCost : 0;
}
else
{
CN_ASSERT(::PurgeComm(hComm_, PURGE_RXABORT));
break;
}
}
}
while (uReadReturn && ++dwReadResult < dwLength);
}
return dwInCount_ += dwReadResult, dwReadResult;
}
#endif
//! <20><><EFBFBD><EFBFBD>I/O<><4F>WinCE<43><45>I/O<><4F> dwWaitTime<6D><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ʱʱ<CAB1><CAB1><EFBFBD>ɳ<EFBFBD>ʱ<EFBFBD><EFBFBD><E1B9B9><EFBFBD><EFBFBD> Ĭ<><C4AC><EFBFBD>趨1/4<><34>
CN_ASSERT(::ReadFile(hComm_, pBuffer, dwLength, &dwReadResult, NULL));
return dwInCount_ += dwReadResult, dwReadResult;
}
//! <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> dwLength<74><68><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD> pBuffer <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>ʶ<EFBFBD><CAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD> <20>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD Read(LPVOID pBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
{
if (!IsOpen())
{
return -1;
}
CN_ASSERT(pBuffer);
if (dwOption_ & EN_RX_BUFFER)
{
BlockBuffer::InnerLock locker(&I_);
return I_.Read(pBuffer, dwLength);
}
#ifdef CN_COMM_FOR_CE
return ReadPort(pBuffer, dwLength, dwWaitTime);
#else
return ReadPort(pBuffer, dwLength, dwWaitTime);
#endif
}
//! <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> dwLength - 1 <20><>ANSI<53>ַ<EFBFBD><D6B7><EFBFBD> szBuffer <20><><EFBFBD><EFBFBD> C ģʽ<C4A3>ַ<EFBFBD><D6B7><EFBFBD>ָ<EFBFBD><D6B8> <20>ʺ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD>ͨѶ
char * ReadString(char *szBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
{
if (!IsOpen())
{
return "";
}
CN_ASSERT(szBuffer);
szBuffer[Read(szBuffer, dwLength - 1, dwWaitTime)] = '\0';
return szBuffer;
}
//! <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> dwLength - 1 <20><>UNICODE<44>ַ<EFBFBD><D6B7><EFBFBD> szBuffer <20><><EFBFBD><EFBFBD> C ģʽ<C4A3>ַ<EFBFBD><D6B7><EFBFBD>ָ<EFBFBD><D6B8> <20>ʺ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD>ͨѶ
wchar_t * ReadString(wchar_t *szBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
{
if (!IsOpen())
{
return L"";
}
CN_ASSERT(szBuffer);
szBuffer[(Read(szBuffer, (dwLength - 1)*sizeof(wchar_t), dwWaitTime) +1)/ sizeof(wchar_t)] = L'\0';
return szBuffer;
}
//! ֱ<><D6B1>д<EFBFBD><D0B4><EFBFBD>˿<EFBFBD>
DWORD WritePort(LPCVOID pBuffer, DWORD dwLength)
{
if (!IsOpen())
{
return -1;
}
if(!CN_ASSERT(IsOpen()) || !dwLength)
return 0;
DWORD dwError;
unsigned long uWriteLength = 0;
if(::ClearCommError(hComm_, &dwError, NULL) && dwError > 0)
::PurgeComm(hComm_, PURGE_TXABORT);
#ifndef CN_COMM_FOR_CE
if (IsOverlappedMode())//! ʹ<><CAB9><EFBFBD>ص<EFBFBD>IO<49>Ƿ<EFBFBD><C7B7><EFBFBD>0<EFBFBD><30>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӽ<EFBFBD><D3BC>ϴ<EFBFBD>д<EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>ɹ<EFBFBD>
{//! <20>ص<EFBFBD>IO<49>³<EFBFBD>ʱ<EFBFBD>ɳ<EFBFBD>ʱ<EFBFBD><EFBFBD><E1B9B9><EFBFBD><EFBFBD> Ĭ<><C4AC>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>*1<><31><EFBFBD><EFBFBD>+10<31><30>
if(!::WriteFile(hComm_, pBuffer, dwLength, &uWriteLength, &WO_)
&& !CN_ASSERT(::GetLastError() == ERROR_IO_PENDING))
uWriteLength = 0;
else
dwOutCount_ += dwLength;
}
else
#endif
{
//! ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IO<49><4F>WINCE<43>³ɹ<C2B3><C9B9><EFBFBD><EFBFBD><EFBFBD>0 ʧ<>ܷ<EFBFBD><DCB7><EFBFBD>ʵ<EFBFBD><CAB5>д<EFBFBD><EFBFBD>ȣ<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD>ʵ<EFBFBD><CAB5>д<EFBFBD><EFBFBD><EBB3A4>, <20><>ʱĬ<CAB1><C4AC>1/4<><34>
BOOL bRet = ::WriteFile(hComm_, pBuffer, dwLength, &uWriteLength, NULL);
int error = ::GetLastError();
dwOutCount_ += uWriteLength;
uWriteLength = (dwLength == uWriteLength) ? uWriteLength : 0;
}
return uWriteLength;
}
//! д EN_TX_BUFFER <20><><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EBBBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>д<EFBFBD><D0B4><EFBFBD>˿<EFBFBD>
DWORD Write(LPCVOID pBuffer, DWORD dwLength)
{
if (!IsOpen())
{
return -1;
}
if (dwLength && (dwOption_&EN_TX_BUFFER))
{
BlockBuffer::InnerLock locker(&O_);
O_.Write(pBuffer, dwLength);
if (dwOption_ & EN_TX_THREAD)
SetEvent(hWatchEvent_);
else
{
#ifdef CN_COMM_FOR_CE
SetCommMask(hComm_, dwWaitEvent_);
#else
if (IsOverlappedMode())
SetCommMask(hComm_, dwWaitEvent_);
else
SetEvent(hWatchEvent_);
#endif
}
return 0;
}
#ifdef CN_COMM_FOR_CE
return WritePort(pBuffer, dwLength);
#else
return WritePort(pBuffer, dwLength);
#endif
}
//! д<><D0B4><EFBFBD><EFBFBD> ANSI<53>ַ<EFBFBD> дANSI C ģʽ<C4A3>ַ<EFBFBD><D6B7><EFBFBD>ָ<EFBFBD><D6B8>
DWORD Write(const char *szBuffer,int nBufferLen)
{
if (!IsOpen())
{
return -1;
}
CN_ASSERT(szBuffer);
return Write((LPCVOID)szBuffer, nBufferLen);
}
//! ǿ<><C7BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2>ȴ<EFBFBD>
void FlushPort()
{
if(CN_ASSERT(IsOpen()))
FlushFileBuffers(hComm_);
}
//! ǿ<><C7BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2>ȴ<EFBFBD>
void Flush()
{
if(CN_ASSERT(IsOpen()))
{
if (dwOption_ & EN_TX_BUFFER)
{
while(O_.SafeSize())
Sleep(50);
}
FlushFileBuffers(hComm_);
}
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
bool TransmitChar(char c)
{
if (CN_ASSERT(IsOpen()))
{
if (::TransmitCommChar(hComm_, c))
return dwOutCount_++, true;
}
return false;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳̿<DFB3><CCBF><EFBFBD>
bool BeginThread(DWORD dwThreadOption = 0)
{
DWORD dwCreationFlags;
if(CN_ASSERT(!hWatchThread_ && !hReadThread_ && !hWriteThread_))
{//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4>²ſ<C2B2><C5BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
bContinue_ = true;
dwCreationFlags = dwOption_ & EN_SUSPEND ? CREATE_SUSPENDED : 0;
if (dwThreadOption)//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<DFB3><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>߳<EFBFBD>
dwOption_ |= dwThreadOption;
#if defined(_MT) && !defined(CN_COMM_FOR_CE)
unsigned int id, rid, wid;
if (dwOption_ & EN_THREAD)
hWatchThread_ = (HANDLE)_beginthreadex(NULL, 0, WatchThreadProc, this, dwCreationFlags, &id);
if (dwOption_ & EN_RX_THREAD)
hReadThread_ = (HANDLE)_beginthreadex(NULL, 0, ReadThreadProc, this, dwCreationFlags, &rid);
if (dwOption_ & EN_TX_THREAD)
hWriteThread_ = (HANDLE)_beginthreadex(NULL, 0, WriteThreadProc, this, dwCreationFlags, &wid);
#else
DWORD id, rid, wid;
if (dwOption_ & EN_THREAD)
hWatchThread_ = ::CreateThread(NULL, 0, WatchThreadProc, this, dwCreationFlags , &id);
if (dwOption_ & EN_RX_THREAD)
hReadThread_ = ::CreateThread(NULL, 0, ReadThreadProc, this, dwCreationFlags, &rid);
if (dwOption_ & EN_TX_THREAD)
hWriteThread_ = ::CreateThread(NULL, 0, WriteThreadProc, this, dwCreationFlags, &wid);
#endif
if (dwOption_ & EN_THREAD)
{
CN_ASSERT(hWatchThread_ != NULL);
hWatchThreadId_ = id;
if (!hWatchThread_)
{
EndThread();
return false;
}
else
{
if (dwOption_ & EN_ABOVE_NORMAL)
SetThreadPriority(hWatchThread_, THREAD_PRIORITY_ABOVE_NORMAL);
}
}
if (dwOption_ & EN_RX_THREAD)
{
CN_ASSERT(hReadThread_ != NULL);
hReadThreadId_ = rid;
if (!hReadThreadId_)
{
EndThread();
return false;
}
else
{
if (dwOption_ & EN_ABOVE_NORMAL)
SetThreadPriority(hReadThread_, THREAD_PRIORITY_ABOVE_NORMAL);
}
}
if (dwOption_ & EN_TX_THREAD)
{
CN_ASSERT(hWriteThread_ != NULL);
hWriteThreadId_ = wid;
if (!hWriteThreadId_)
{
EndThread();
return false;
}
else
{
if (dwOption_ & EN_ABOVE_NORMAL)
SetThreadPriority(hWriteThread_, THREAD_PRIORITY_ABOVE_NORMAL);
}
}
return true;
}
return false;
}
//! <20><>ͣ<EFBFBD>߳<EFBFBD>
bool SuspendThread(int iOption = EN_THREAD)
{
return ::SuspendThread(GetThread(iOption)) != 0xFFFFFFFF;
}
//! <20>ָ<EFBFBD><D6B8>߳<EFBFBD>
bool ResumeThread(int iOption = EN_THREAD)
{
return ::ResumeThread(GetThread(iOption)) != 0xFFFFFFFF;
}
//! <20><>ֹ<EFBFBD>߳<EFBFBD>
bool EndThread(DWORD dwWaitTime = 500)
{
if(hWatchThread_ || hReadThread_ || hWriteThread_)
{
if ((dwOption_&EN_FLUSH_ALL) && (dwOption_&EN_TX_BUFFER))
{//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>EN_FLUSH_ALL<4C><4C><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>ȴ<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>գ<EFBFBD><D5A3><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>̲߳<DFB3><CCB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
while(O_.Size())
Sleep(50);
}
bContinue_ = false;
#ifdef CN_COMM_FOR_CE
::SetCommMask(hComm_, 0);
#else
if (IsOverlappedMode())
::SetCommMask(hComm_, 0);
#endif
if (hWatchThread_)
{
SetEvent(hWatchEvent_);
if(::WaitForSingleObject(hWatchThread_, dwWaitTime) != WAIT_OBJECT_0)
if(!::TerminateThread(hWatchThread_, 0))
return false;
::CloseHandle(hWatchThread_);
hWatchThread_ = NULL;
}
if (hReadThread_)
{
SetEvent(hReadEvent_);
if(::WaitForSingleObject(hReadThread_, dwWaitTime) != WAIT_OBJECT_0)
if(!::TerminateThread(hReadThread_, 0))
return false;
::CloseHandle(hReadThread_);
hReadThread_ = NULL;
}
if (hWriteThread_)
{
SetEvent(hWriteEvent_);
if(::WaitForSingleObject(hWriteThread_, dwWaitTime) != WAIT_OBJECT_0)
if(!::TerminateThread(hWriteThread_, 0))
return false;
::CloseHandle(hWriteThread_);
hWriteThread_ = NULL;
}
return true;
}
return false;
}
//! <20>رմ<D8B1><D5B4><EFBFBD> ͬʱҲ<CAB1>رչ<D8B1><D5B9><EFBFBD><EFBFBD>߳<EFBFBD>
virtual void Close(DWORD dwWaitTime = 500)
{
if(IsOpen())
{
EndThread(dwWaitTime);//! ͬ<><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
if (dwOption_&EN_FLUSH || dwOption_&EN_FLUSH_ALL)
FlushFileBuffers(hComm_);
::PurgeComm(hComm_, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_RXABORT);
::CloseHandle(hComm_);
hComm_ = INVALID_HANDLE_VALUE;
}
}
//! <20><><EFBFBD><EFBFBD>
void Lock()
{
::EnterCriticalSection(&CS_);
}
//! <20><><EFBFBD><EFBFBD>
void Unlock()
{
::LeaveCriticalSection(&CS_);
}
//! <20>Զ<EFBFBD><D4B6><EFBFBD> <20><><EFBFBD>ں<EFBFBD><DABA><EFBFBD><EFBFBD>ڲ<EFBFBD> <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
struct InnerLock
{
ComComm* ptr;//!< ComComm <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
//! <20><><EFBFBD><EFBFBD>
InnerLock(ComComm* p) : ptr(p)
{
ptr->Lock();
}
//! <20><><EFBFBD><EFBFBD>
~InnerLock()
{
ptr->Unlock();
}
};
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ڲ<EFBFBD><DAB2><EFBFBD> DCB
DCB *GetState(DCB *pDcb = NULL)
{
return CN_ASSERT(IsOpen()) && ::GetCommState(hComm_, pDcb == NULL ? &DCB_ : pDcb) == TRUE ? (pDcb == NULL ? &DCB_ : pDcb) : NULL;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ڲ<EFBFBD><DAB2><EFBFBD> DCB
bool SetState(DCB *pDcb = NULL)
{
return CN_ASSERT(IsOpen()) ? ::SetCommState(hComm_, pDcb == NULL ? &DCB_ : pDcb) == TRUE : false;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>ֹͣλ<D6B9><CEBB><EFBFBD><EFBFBD> ***
bool SetState(DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT)
{
if(CN_ASSERT(IsOpen()))
{
if(::GetCommState(hComm_, &DCB_) != TRUE)
return false;
DCB_.BaudRate = dwBaudRate;
DCB_.ByteSize = btByteSize;
DCB_.Parity = btParity;
DCB_.StopBits = btStopBits;
DCB_.fParity = (btParity != NOPARITY);
return ::SetCommState(hComm_, &DCB_) == TRUE;
}
return false;
}
#ifndef CN_COMM_FOR_CE
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ڲ<EFBFBD><DAB2><EFBFBD> ֧<><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD> "9600, n, 8, 1"
bool SetState(LPCTSTR szSetStr)
{
if(CN_ASSERT(IsOpen()))
{
if(!::GetCommState(hComm_, &DCB_))
return false;
if(!BuildCommDCB(szSetStr, &DCB_))
return false;
DCB_.fParity = (DCB_.Parity != NOPARITY);
BOOL bRet = ::SetCommState(hComm_, &DCB_) == TRUE;
bool smallBool = false;
bRet == 0 ? smallBool = false : smallBool = true;
return smallBool;
}
return false;
}
#endif
//! <20><><EFBFBD>ó<EFBFBD>ʱ<EFBFBD>
LPCOMMTIMEOUTS GetTimeouts(LPCOMMTIMEOUTS lpCO = NULL)
{
return CN_ASSERT(IsOpen()) && ::GetCommTimeouts(hComm_, lpCO ? lpCO : &CO_) == TRUE ? (lpCO ? lpCO : &CO_) : NULL;
}
//! <20><><EFBFBD>ó<EFBFBD>ʱ
bool SetTimeouts(LPCOMMTIMEOUTS lpCO = NULL)
{
return CN_ASSERT(IsOpen()) ? ::SetCommTimeouts(hComm_, lpCO ? lpCO : &CO_) == TRUE : false;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4>ڵ<EFBFBD>I/O<><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
bool Setup(DWORD dwInputSize = 4096, DWORD dwOutputSize = 4096)
{
return CN_ASSERT(IsOpen()) ? ::SetupComm(hComm_, dwInputSize, dwOutputSize) == TRUE : false;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD>˿ڹ<CBBF><DAB9><EFBFBD>
bool Escape(DWORD dwType)
{
return CN_ASSERT(IsOpen()) ? EscapeCommFunction(hComm_, dwType) != 0 : false;
}
//! <20><><EFBFBD>õ<EFBFBD><C3B5>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD>״̬
DWORD GetModemStatus()
{
DWORD dwModemStat = 0;
return CN_ASSERT(IsOpen()) && GetCommModemStatus(hComm_, &dwModemStat) ? dwModemStat : 0;
}
//! <20><><EFBFBD>ö˿ڲ<CBBF><DAB2><EFBFBD> \param[in] pCP <20>ṹָ<E1B9B9><D6B8> <20><><EFBFBD><EFBFBD>pCP==NULL, ComComm<6D><6D><EFBFBD>Ӷѷ<D3B6><D1B7><EFBFBD><EFBFBD>ڴ<EFBFBD>, <20><><EFBFBD><EFBFBD>ComComm<6D><6D><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>, <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Լ<EFBFBD><D4BC>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
LPCOMMPROP GetProperties(LPCOMMPROP pCP = NULL)
{
if (CN_ASSERT(IsOpen()))
{
if (!pCP)
{
#ifdef CN_COMM_FOR_CE
USHORT dwSize = sizeof(COMMPROP);
#else
USHORT dwSize = sizeof(COMMPROP) + sizeof(MODEMDEVCAPS);
#endif
if (!pCP_)
pCP_ = (LPCOMMPROP) new BYTE[dwSize];
if (pCP_)
{
memset(pCP_, 0, dwSize);
pCP_->wPacketLength = dwSize;
#ifndef CN_COMM_FOR_CE
pCP_->dwProvSubType = PST_MODEM;
#endif
pCP_->dwProvSpec1 = COMMPROP_INITIALIZED;
pCP = pCP_;
}
}
}
return pCP && GetCommProperties(hComm_, pCP) ? pCP : NULL;
}
//! <20><>ȡ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD>ʶ
DWORD GetMask()
{
DWORD dwMask;
return CN_ASSERT(IsOpen()) && GetCommMask(hComm_, &dwMask) ? dwMask : 0;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD>˿ڻ<CBBF><DABB><EFBFBD><EFBFBD><EFBFBD>
bool Purge(DWORD dwPara = PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR)
{
return CN_ASSERT(IsOpen()) ? ::PurgeComm(hComm_, dwPara)==TRUE : false;
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD ClearError()
{
DWORD dwError;
return CN_ASSERT(IsOpen()) && ::ClearCommError(hComm_, &dwError, NULL) ? dwError : 0;
}
//! <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
DWORD GetQueueCount(bool bInput = true)
{
COMSTAT Stat;
DWORD dwError;
return CN_ASSERT(IsOpen()) && ::ClearCommError(hComm_, &dwError, &Stat) ? (bInput ? Stat.cbInQue : Stat.cbOutQue) : (DWORD)-1L;
}
//! <20><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD> CTS ON
bool CheckCTS()
{
return (GetModemStatus()&MS_CTS_ON) != 0;
}
//! <20><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD> DSR ON
bool CheckDSR()
{
return (GetModemStatus()&MS_DSR_ON) != 0;
}
//! <20><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD> Ring ON
bool CheckRING()
{
return (GetModemStatus()&MS_RING_ON) != 0;
}
//! <20><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD> RLSD ON
bool CheckRLSD()
{
return (GetModemStatus()&MS_RLSD_ON) != 0;
}
//! DTR <20><>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>
bool SetDTR(bool bSetOrClr = true)
{
return Escape(bSetOrClr ? SETDTR : CLRDTR);
}
//! RTS <20><>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>
bool SetRTS(bool bSetOrClr = true)
{
return Escape(bSetOrClr ? SETRTS : CLRRTS);
}
//! <20><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD>
bool SetBreak(bool bSetOrClr = true)
{
return Escape(bSetOrClr ? SETBREAK : CLRBREAK);
}
#ifdef CN_COMM_FOR_CE
//! WINCE
bool SetIR(bool bSetOrClr)
{
return Escape(bSetOrClr ? SETIR : CLRIR);
}
#endif
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SETXON SETXOFF
bool SetX(bool bOnOrOff)
{
return Escape(bOnOrOff ? SETXON : SETXOFF);
}
//! <20><><EFBFBD><EFBFBD>ͨѶ<CDA8>ص㿪<D8B5><E3BFAA><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD> <20><>һЩ<D2BB><D0A9>չ<EFBFBD><D5B9>֧<EFBFBD>ֺ<EFBFBD>API<50>ҽ<EFBFBD>
class BlockBuffer
{
public:
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>
struct Block
{
DWORD B_; //!< <20><>ʼƫ<CABC><C6AB>
DWORD E_; //!< <20><><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB>
DWORD S_; //!< <20><><EFBFBD><EFBFBD>С <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>Сֵ<D0A1><D6B5>CN_COMM_BUFFER_MIN_BLOCK_SIZE<5A><45><EFBFBD><EFBFBD>
Block* N_; //!< <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
BYTE P_[4]; //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> ʵ<>ʴ<EFBFBD>С<EFBFBD><D0A1>S_<53><5F><EFBFBD><EFBFBD>
//! <20><><EFBFBD><EFBFBD>
DWORD Capacity() { return S_; }
//! ʵ<>ʴ<EFBFBD>С
DWORD Size() { return E_ - B_; }
//! <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
BYTE* Begin() { return P_ + B_; }
//! ĩ<>˻<EFBFBD><CBBB><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
BYTE* End() { return P_ + E_; }
//! <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
Block* Next() { return N_; }
//! <20>Ƿ<EFBFBD><C7B7><EFBFBD>
bool IsEmpty() { return B_ == E_; }
//! <20><><EFBFBD>д<EFBFBD>С
DWORD FreeSize() { return S_ - E_; }
};
//! <20><><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
struct Iterator
{
BlockBuffer* P_; //!< <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
Block* B_; //!< <20><>ǰ<EFBFBD><C7B0>ָ<EFBFBD><D6B8>
DWORD I_; //!< <20><>ǰ<EFBFBD><C7B0>ƫ<EFBFBD><C6AB>
DWORD O_; //!< ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB>
//! <20><><EFBFBD><EFBFBD>
Iterator(BlockBuffer *P = NULL, Block* B = NULL, DWORD I = 0, DWORD O = 0)
: P_(P), B_(B), I_(I), O_(O)
{
}
//! <20>Ƿ<EFBFBD><C7B7><EFBFBD>Ч
operator bool()
{
return B_ && I_<B_->E_&&I_>=B_->B_;
}
//! <20>Ƿ<EFBFBD><C7B7><EFBFBD>д
bool CanWrite()
{
return B_ && I_ < B_->S_;
}
//! ȡֵ<C8A1><D6B5><EFBFBD><EFBFBD>
BYTE& operator *()
{
CN_ASSERT( P_ && B_ && I_<B_->E_&&I_>=B_->B_);
return B_->P_[I_];
}
//! <20>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ++Iter;
Iterator& operator ++ ()
{
return operator +=(1);
}
//! <20>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Iter++;
Iterator& operator ++ (int)
{
return operator +=(1);
}
//! <20>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param dwOffset Ϊƫ<CEAA><C6AB><EFBFBD><EFBFBD>
Iterator& operator += (DWORD dwOffset)
{
while (dwOffset)
{
if (I_+dwOffset < B_->E_)
I_ += dwOffset, O_ += dwOffset, dwOffset = 0;
else
dwOffset -= B_->E_-I_, I_ += B_->E_-I_, O_ += B_->E_-I_, B_ = B_->N_, I_ = 0;
}
return *this;
}
//! <20>Ƚ<EFBFBD>
bool operator == (const Iterator& iter)
{
return (P_ == iter.P_) && (B_ == iter.B_) && (I_ == iter.I_);
}
};
//! <20><>Ԫ
friend struct Iterator;
//! <20><><EFBFBD><EFBFBD>
void Lock()
{
::EnterCriticalSection(&C_);
}
//! <20><><EFBFBD><EFBFBD>
void Unlock()
{
::LeaveCriticalSection(&C_);
}
//! <20>Զ<EFBFBD><D4B6><EFBFBD>
struct InnerLock
{
BlockBuffer* ptr;//!<<3C><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
///<2F><><EFBFBD><EFBFBD>
InnerLock(BlockBuffer* p) : ptr(p)
{
if (ptr)
ptr->Lock();
}
///<2F><><EFBFBD><EFBFBD>
~InnerLock()
{
if (ptr)
ptr->Unlock();
}
};
//! <20><><EFBFBD><EFBFBD>
BlockBuffer()
{
::InitializeCriticalSection(&C_);
S_ = 0, F_ = L_ = NULL, M_ = CN_COMM_BUFFER_MIN_BLOCK_SIZE;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>ͷſռ<C5BF>
virtual ~BlockBuffer()
{
Clear();
::DeleteCriticalSection(&C_);
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Iterator Begin()
{
return Iterator(this, F_, F_? F_->B_ : 0, 0);
}
//! <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
void SetMinBlockSize(DWORD dwMinSize)
{
M_ = dwMinSize;
}
//! <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
DWORD GetMinBlockSize()
{
return M_;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
DWORD Size()
{
return S_;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
DWORD SafeSize()
{
InnerLock lock(this);
return S_;
}
//! д<><D0B4>ANSI<53>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \sa Write(LPCVOID lpBuf, DWORD dwSize)
DWORD Write(const char* lpBuf)
{
return Write(lpBuf, strlen(lpBuf));
}
//! д<><D0B4>UNICODE<44>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \sa Write(LPCVOID lpBuf, DWORD dwSize)
DWORD Write(const wchar_t* lpBuf)
{
return Write(lpBuf, wcslen(lpBuf)*sizeof(wchar_t));
}
//! д<><EFBFBD><EBBBBA><EFBFBD><EFBFBD> \param[out] lpBuf Ŀ<><EFBFBD><EABBBA><EFBFBD><EFBFBD> \param[in] dwSize <20><><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> \return ʵ<>ʸ<EFBFBD><CAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
DWORD Write(LPCVOID lpBuf, DWORD dwSize)
{
DWORD dwTemp = dwSize, dwFree = FreeSize(), dwCopy = 0;
if (dwFree)//! <20><><EFBFBD>Ȳ<EFBFBD><C8B2><EFBFBD>ĩβ<C4A9><CEB2><EFBFBD>У<EFBFBD><D0A3><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
dwCopy = dwFree > dwSize ? dwSize : dwFree;
memcpy(L_->P_ + L_->E_, lpBuf, dwCopy);
dwTemp -= dwCopy, L_->E_ += dwCopy;
}
if (dwTemp)//! ʣ<><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD>µĿռ䲢д<E4B2A2><D0B4>
{
memcpy(NewBlock(dwSize)->P_, ((LPBYTE)lpBuf )+ dwCopy, dwTemp);
L_->E_ += dwTemp;
}
S_ += dwSize;
return dwSize;
}
//! <20>̰߳<DFB3>ȫд<C8AB><EFBFBD><EBBBBA><EFBFBD><EFBFBD> \sa Write(LPCVOID lpBuf, DWORD dwSize)
DWORD SafeWrite(LPCVOID lpBuf, DWORD dwSize)
{
InnerLock lock(this);
return Write(lpBuf, dwSize);
}
//! <20>̰߳<DFB3>ȫд<C8AB><D0B4>ANSI<53>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \sa Write(LPCVOID lpBuf, DWORD dwSize)
DWORD SafeWrite(const char* lpBuf)
{
InnerLock lock(this);
return Write(lpBuf, strlen(lpBuf));
}
//! <20>̰߳<DFB3>ȫд<C8AB><D0B4>UNICODE<44>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \sa Write(LPCVOID lpBuf, DWORD dwSize)
DWORD SafeWrite(const wchar_t* lpBuf)
{
InnerLock lock(this);
return Write(lpBuf, wcslen(lpBuf)*sizeof(wchar_t));
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[out] lpBuf Ŀ<><EFBFBD><EABBBA><EFBFBD><EFBFBD> \param[in] dwSize <20><><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> \param[in] dwStart Դ<><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼƫ<CABC><C6AB>ֵ \return ʵ<>ʸ<EFBFBD><CAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
DWORD Copy(LPVOID lpBuf, DWORD dwSize, DWORD dwStart = 0)
{
CN_ASSERT(lpBuf);
if (!F_ || !dwSize || dwStart >= S_)
return 0;
DWORD dwTemp, dwIndex;
Block * pCur = F_, *pNext = F_->N_;
for (dwTemp = 0, dwIndex = pCur->B_; dwTemp < dwStart; pCur = pCur->N_, dwIndex = pCur ? pCur->B_ : 0)
{
if (dwStart - dwTemp < pCur->E_ - pCur->B_)
{
dwIndex = pCur->B_ + dwStart - dwTemp;
break;
}
dwTemp += pCur->E_ - pCur->B_;
}
for (dwTemp = 0; dwTemp < dwSize && pCur; pCur = pCur->N_, dwIndex = pCur ? pCur->B_ : 0)
{
if (dwSize - dwTemp < pCur->E_ - dwIndex)
{
memcpy((LPBYTE)lpBuf+dwTemp, pCur->P_ + dwIndex, dwSize - dwTemp );
dwTemp = dwSize;
break;
}
else
{
memcpy((LPBYTE)lpBuf+dwTemp, pCur->P_ + dwIndex, pCur->E_ - dwIndex);
dwTemp += pCur->E_ - dwIndex;
}
}
return dwTemp;
}
//! <20>̰߳<DFB3>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \sa Copy(LPVOID lpBuf, DWORD dwSize, DWORD dwStart=0)
DWORD SafeCopy(LPVOID lpBuf, DWORD dwSize, DWORD dwStart = 0)
{
InnerLock lock(this);
return Copy(lpBuf, dwSize, dwStart);
}
/*! \param[out] lpBuf Ŀ<><EFBFBD><EABBBA><EFBFBD><EFBFBD> ΪNULLʱ<4C><CAB1>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \param[in] dwSize <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> \return ʵ<>ʸ<EFBFBD><CAB8>ƻ<EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> */
//! <20><><EFBFBD>Ʋ<EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>lpBuf
DWORD Read(LPVOID lpBuf, DWORD dwSize)
{
DWORD dwTemp = 0, dwCopy;
for (Block * pCur = F_, *pNext = NULL; dwTemp<dwSize && pCur; pCur = pNext)
{
if (dwSize-dwTemp > pCur->E_-pCur->B_ )
dwCopy = pCur->E_ - pCur->B_;
else
dwCopy = dwSize - dwTemp;
if (lpBuf)
memcpy((LPBYTE)lpBuf+dwTemp, pCur->P_ + pCur->B_, dwCopy);
pNext = pCur->N_, dwTemp += dwCopy;
if (dwCopy == pCur->E_-pCur->B_)
{//! ɾ<><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>п<EFBFBD>, <20><>һ<EFBFBD><EFBFBD><E3B1A3>1<EFBFBD><31><EFBFBD><EFBFBD>, <20><>С<EFBFBD><D0A1>4*CN_COMM_BUFFER_MIN_BLOCK_SIZE<5A><45><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (pNext || pCur->S_>(M_<<2))
{
delete[] (BYTE*)pCur;
F_ = pNext;
if (!F_)
L_ = NULL;
}
else
pCur->B_ = pCur->E_ = 0;
}
else
pCur->B_ += dwCopy;
S_ -= dwCopy;
}
return dwTemp;
}
//! <20><><EFBFBD><EFBFBD>ANSI<53>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char* ReadString(char* lpBuf, DWORD dMaxSize)
{
lpBuf[Read(lpBuf, dMaxSize)] = '\0';
return lpBuf;
}
//! <20><><EFBFBD><EFBFBD>UNICODE<44>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
wchar_t* ReadString(wchar_t* lpBuf, DWORD dMaxSize)
{
lpBuf[(Read(lpBuf, dMaxSize*sizeof(wchar_t))+1) / sizeof(wchar_t)] = L'\0';
return lpBuf;
}
//! <20>̰߳<DFB3>ȫ<EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
DWORD SafeRead(LPVOID lpBuf, DWORD dwSize)
{
InnerLock lock(this);
return Read(lpBuf, dwSize);
}
//! <20>̰߳<DFB3>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>ANSI<53>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char* SafeReadString(char* lpBuf, DWORD dMaxSize)
{
InnerLock lock(this);
return ReadString(lpBuf, dMaxSize);
}
//! <20>̰߳<DFB3>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>UNICODE<44>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
wchar_t* SafeReadString(wchar_t* lpBuf, DWORD dMaxSize)
{
InnerLock lock(this);
return ReadString(lpBuf, dMaxSize);
}
//! <20><><EFBFBD><EFBFBD> \param bDeleteAll Ϊtrueʱ<65>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>
void Clear(bool bDeleteAll = false)
{
if (F_ && (F_==L_) && F_->S_>(M_<<2))
{
DWORD S = F_->S_;
memset(F_, 0, sizeof(Block)), F_->S_ = S;
}
else
{
for (Block* t = F_; t; delete F_)
F_ = t, t = t->N_;
F_ = L_ = NULL, S_ = 0;
}
}
//! <20>̰߳<DFB3>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \sa void Clear(bool bDeleteAll = false)
void SafeClear(bool bDeleteAll = false)
{
InnerLock lock(this);
Clear(bDeleteAll);
}
//! <20><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>ָ<EFBFBD><D6B8> \param bFirst Ϊtrueʱ<65><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><CEB2>ָ<EFBFBD><D6B8>
Block* GetBlockPtr(bool bFirst = true)
{
return bFirst ? F_ : L_;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><CEB2><EFBFBD>Ŀ<EFBFBD><C4BF>пռ<D0BF>
DWORD FreeSize()
{
return L_ ? L_->S_-L_->E_ : 0 ;
}
//! <20><><EFBFBD>ù<EFBFBD>API<50><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ֱд<D6B1><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>СdwSize <20><><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¿<EFBFBD> <20><><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>β<EFBFBD><CEB2><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ָ<EFBFBD><D6B8> β<><CEB2><EFBFBD>޿<EFBFBD><DEBF>з<EFBFBD><D0B7><EFBFBD>NULL
LPVOID GetFreePtr(DWORD dwSize = 0)
{
if (dwSize)
return FreeSize() > dwSize ? L_->P_ + L_->E_ : NewBlock(dwSize)->P_;
else
return L_ ? L_->P_ + L_->E_ : NULL;
}
/*! \param[in] dwSize <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>
\code strcpy(GetFreePtr(100), "test"), Release(4); //<2F><>ȡ100<30>ֽڵĻ<DAB5><C4BB><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ֽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD>ֽ<EFBFBD> \endcode
*/
//! <20><><EFBFBD><EFBFBD>APIֱ<49><D6B1>д<EFBFBD><D0B4><EFBFBD><EFBFBD>GetFreePtr()<29><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ָ<EFBFBD><D6B8>, ͬ<><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
DWORD Release(DWORD dwSize)
{
return (dwSize <= L_->S_) ? (L_->E_ += dwSize, S_ += dwSize, dwSize) : 0;
}
//! <20><><EFBFBD>õ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
LPVOID GetPtr()
{
return F_ ? F_->P_ + F_->B_ : NULL;
}
//! <20><><EFBFBD>õ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD>С
DWORD GetPtrSize()
{
return F_ ? F_->E_ - F_->B_ : 0;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1 Ч<>ʺܵ<CABA> <20>Ƽ<EFBFBD><C6BC>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ӷ<EFBFBD><D3B7>ʿ<EFBFBD><CABF>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BYTE& operator[](DWORD dwOffset)
{
CN_ASSERT(F_);
if (F_ == L_)
{
CN_ASSERT(F_->S_ > dwOffset);
return F_->P_[dwOffset];
}
else
{
Iterator iter = Begin();
iter += dwOffset;
CN_ASSERT(iter);
return *iter;
}
}
protected:
//! <20>½<EFBFBD><C2BD><EFBFBD> <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><CEB2>
Block* NewBlock(DWORD dwSize)
{
dwSize = dwSize < M_ ? M_ : dwSize;
Block * pNew = (Block *) new BYTE[sizeof(Block) - 4 + dwSize];
if (pNew)
{
memset(pNew, 0, sizeof(Block));
pNew->S_ = dwSize;
if (L_)
L_->N_ = pNew, L_ = pNew;
else
F_ = L_ = pNew;
}
return pNew;
}
Block* F_;//!< ͷָ<CDB7><D6B8>
Block* L_;//!< βָ<CEB2><D6B8>
DWORD S_;//!< <20><>С
DWORD M_;//!< <20><><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
CRITICAL_SECTION C_;//!< <20><><EFBFBD>
};
#if defined(CN_COMM_MFC_EXCEPTION)
/*! <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CN_COMM_MFC_EXCEPTION CN_ASSERT \n <20><>ʹ<EFBFBD><CAB9>throw new MfcException(msg);<3B><><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD>MFC<46>쳣(VC++) */
//! <20><><EFBFBD><EFBFBD>MFC<46><43><EFBFBD>
class MfcException : public CException
{
public:
//! <20><><EFBFBD><EFBFBD><ECBAAF><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>CException<6F>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
MfcException(LPCTSTR szMsg) : CException(TRUE)
{
lstrcpy(szMsg_, szMsg);
#ifdef _DEBUG
CException::m_bReadyForDelete = TRUE;
#endif
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>Ϣ
BOOL GetErrorMessage( LPTSTR lpszError, UINT nMaxError, PUINT pnHelpContext = NULL )
{
#ifndef CN_COMM_FOR_CE
lstrcpyn(lpszError, szMsg_, nMaxError);
#else
_tcsncpy(lpszError, szMsg_, nMaxError - 1);
lpszError[nMaxError - 1] = _T('\0');
#endif
return TRUE;
}
protected:
TCHAR szMsg_[256]; //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ <20><>ʽ<EFBFBD><CABD>CN_ASSERT(<28><><EFBFBD><EFBFBD>ʽ) failed; ComComm(<28>к<EFBFBD>); Code(GetLastError()); <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
#endif
//! <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD>׳<EFBFBD><D7B3>쳣; δ<><CEB4><EFBFBD><EFBFBD><EFBFBD>쳣: DEBUG<55><20><><EFBFBD><EFBFBD>̨<EFBFBD><EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ <20><><EFBFBD>˳<EFBFBD>; Release<73><EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>û<EFBFBD>Ҫ<EFBFBD><D2AA>
static bool Assert(LPCTSTR szMessage)
{
return false;
//#if defined(_DEBUG) || defined(CN_COMM_STD_EXCEPTION) || defined(CN_COMM_VCL_EXCEPTION) || defined(CN_COMM_MFC_EXCEPTION)
// TCHAR szMsg[256];
// DWORD dwError, dwLength;
//
// _tcscpy_s(szMsg, szMessage);
// dwError = GetLastError();
// if (dwError)//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(GetLastError())<29><>Ϊ 0 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// {
// dwLength = _tcslen(szMsg);
// _sntprintf_s(szMsg + dwLength, 256 - _tcslen(szMsg), 256, _T("Code:%d; "), dwError);
// dwLength = _tcslen(szMsg);
// FormatMessage(
// FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
// NULL,
// dwError,
// MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// szMsg + dwLength - 1,
// 256 - dwLength - 1,
// NULL
// );
// }
//#else
// ;// Release<73>汾 ʲô<CAB2><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ԥ<><D4A4>
//#endif
//#if defined(CN_COMM_STD_EXCEPTION)
// #ifdef _UNICODE
// char szTemp[512] = {0};
// WideCharToMultiByte(CP_ACP, 0, szMsg, -1, szTemp, wcslen(szMsg)*sizeof(wchar_t), NULL, NULL);
// throw std::runtime_error(szTemp);
// #else
// throw std::runtime_error(szMsg);
// #endif
//#elif defined(CN_COMM_VCL_EXCEPTION)
// throw Exception(szMsg);
//#elif defined(CN_COMM_MFC_EXCEPTION)
// throw (new MfcException(szMsg));
//#elif defined(_DEBUG)
// OutputDebugString(szMsg);
// #ifdef _CONSOLE
// // <20><>Ҫ setlocale(LC_ALL, "chs"); <20><><EFBFBD><EFBFBD>̨<EFBFBD>ſ<EFBFBD><C5BF><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>UNICODE<44><45><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ANSI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// #ifdef _UNICODE
// char szTemp[512] = {0};
// WideCharToMultiByte(CP_ACP, 0, szMsg, -1, szTemp, wcslen(szMsg)*sizeof(wchar_t), NULL, NULL);
// fprintf(stderr, szTemp);
// #else
// fprintf(stderr, szMsg);
// #endif
// system("pause");
// exit(1);
// #else
// switch(MessageBox(NULL, szMsg, _T("CN_ASSERT"), MB_ABORTRETRYIGNORE))
// {
// case IDABORT:
// exit(1);
// case IDRETRY:
// DebugBreak();
// break;
// case IDIGNORE:
// break;
// }
// #endif
//#else
// ;// Release<73>汾 ʲô<CAB2><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ԥ<><D4A4>
//#endif
// return false;
}
protected:
DWORD m_lReadTimeout;
ComCallback m_pComCb; //!< <20><><EFBFBD>ݻص<DDBB>
void* m_pUser; //!< <20><><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD>
std::function<void()> m_pfn;
DWORD dwOption_; //!< <20>ؼ<EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD> <20>ڹ<EFBFBD><DAB9><EFBFBD><ECBAAF><EFBFBD><EFBFBD><EFBFBD>
HANDLE hComm_; //!< <20><><EFBFBD>ھ<EFBFBD><DABE><EFBFBD>
DWORD dwPort_; //!< <20><><EFBFBD>ں<EFBFBD><30><CEAA><EFBFBD><EFBFBD><E2B4AE> -1Ϊ<31><CEAA>Ч <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD>
TCHAR szName_[64]; //!< <20><><EFBFBD><EFBFBD><E6B4AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>COM1<4D><31><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
CRITICAL_SECTION CS_; //!< <20>ٽ绥<D9BD><E7BBA5><EFBFBD><EFBFBD>
DCB DCB_; //!< <20><><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>ֹͣλ<D6B9><CEBB><EFBFBD><EFBFBD>
COMMTIMEOUTS CO_; //!< <20><>ʱ<EFBFBD>
COMMPROP* pCP_; //!< <20><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>
BlockBuffer I_; //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BlockBuffer O_; //!< д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD dwInCount_; //!< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD dwOutCount_; //!< д<><D0B4><EFBFBD><EFBFBD>
bool bContinue_; //!< <20>̼߳<DFB3><CCBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD>־
DWORD dwWaitEvent_; //!< WaitCommEvent <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>¼<EFBFBD>
HANDLE hWatchThread_; //!< <20><><EFBFBD>Ӹ<EFBFBD><D3B8><EFBFBD><EFBFBD>߳<EFBFBD>
DWORD hWatchThreadId_; //!< <20><><EFBFBD>Ӹ<EFBFBD><D3B8><EFBFBD><EFBFBD>߳<EFBFBD> ID
HANDLE hWatchEvent_; //!< ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
HANDLE hReadThread_; //!< <20><><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD>߳<EFBFBD> ʵ<><CAB5>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>
DWORD hReadThreadId_; //!< <20><><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD>߳<EFBFBD> ID
HANDLE hReadEvent_; //!< ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
HANDLE hWriteThread_; //!< <20><><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>߳<EFBFBD> ʵ<><CAB5>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>
DWORD hWriteThreadId_; //!< <20><><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>߳<EFBFBD> ID
HANDLE hWriteEvent_; //!< ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
DWORD dwNotifyNum_; //!< <20><><EFBFBD>ܶ<EFBFBD><DCB6><EFBFBD><EFBFBD>ֽ<EFBFBD>(>=dwNotifyNum_)<29><><EFBFBD><EFBFBD>֪ͨ<CDA8><D6AA>Ϣ
#ifndef CN_COMM_FOR_CE
OVERLAPPED RO_; //!< <20>ص<EFBFBD>I/O ReadFile
OVERLAPPED WO_; //!< <20>ص<EFBFBD>I/O WriteFile
OVERLAPPED EO_; //!< <20>ص<EFBFBD>I/O WaitCommEvent
#endif
//! <20><>ʼ<EFBFBD><CABC>
virtual void Init()
{
::InitializeCriticalSection(&CS_);
memset(szName_, 0, 64*sizeof(TCHAR));
memset(&DCB_, 0, sizeof(DCB_));
DCB_.DCBlength = sizeof(DCB_);
m_pComCb = NULL;
m_pUser = NULL;
hComm_ = INVALID_HANDLE_VALUE;
dwPort_ = (DWORD)-1;
dwOutCount_ = 0;
dwInCount_ = 0;
dwWaitEvent_ = CN_COMM_WAIT_EVENT;
hWatchThread_ = NULL;
hReadThread_ = NULL;
hWriteThread_ = NULL;
hWatchThreadId_ = 0;
hReadThreadId_ = 0;
hWriteThreadId_ = 0;
dwNotifyNum_ = 0;
pCP_ = NULL;
#ifndef CN_COMM_FOR_CE
memset(&RO_, 0, sizeof(RO_));
memset(&WO_, 0, sizeof(WO_));
memset(&EO_, 0, sizeof(EO_));
RO_.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
CN_ASSERT(RO_.hEvent != NULL);
WO_.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
CN_ASSERT(WO_.hEvent != NULL);
EO_.hEvent= ::CreateEvent(NULL, TRUE, FALSE, NULL);
CN_ASSERT(EO_.hEvent != NULL);
#endif
hWatchEvent_ = ::CreateEvent(NULL, TRUE, FALSE, NULL);
CN_ASSERT(hWatchEvent_ != NULL);
hReadEvent_ = ::CreateEvent(NULL, TRUE, FALSE, NULL);
CN_ASSERT(hReadEvent_ != NULL);
hWriteEvent_ = ::CreateEvent(NULL, TRUE, FALSE, NULL);
CN_ASSERT(hWriteEvent_ != NULL);
m_lReadTimeout = 250;//250ms
}
//! <20><><EFBFBD><EFBFBD>
virtual void Destroy()
{
#ifndef CN_COMM_FOR_CE
if(RO_.hEvent != NULL)
CloseHandle(RO_.hEvent);
if(WO_.hEvent != NULL)
CloseHandle(WO_.hEvent);
if(EO_.hEvent != NULL)
CloseHandle(EO_.hEvent);
#endif
if(hWatchEvent_ != NULL)
CloseHandle(hWatchEvent_);
if(hReadEvent_ != NULL)
CloseHandle(hReadEvent_);
if(hWriteEvent_ != NULL)
CloseHandle(hWriteEvent_);
if (pCP_)
delete[] ((BYTE*)pCP_);
::DeleteCriticalSection(&CS_);
}
//! <20>󶨴<EFBFBD><F3B6A8B4><EFBFBD>
void BindPort(DWORD dwPort)
{
dwPort_ = dwPort;
#if defined(CN_COMM_FOR_CE)
wsprintf(szName_, _T("COM%d:"), dwPort);
#else
wsprintf(szName_, _T("\\\\.\\COM%d"), dwPort);
#endif
}
//! <20>򿪴<EFBFBD><F2BFAAB4><EFBFBD>
virtual bool OpenPort()
{
CN_ASSERT(!IsOpen());
if(IsOpen())
Close();
hComm_ = ::CreateFile(
szName_,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | (IsOverlappedMode() ? FILE_FLAG_OVERLAPPED : 0),
NULL
);
return IsOpen();
}
//! <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>
virtual bool SetupPort()
{
if(!CN_ASSERT(IsOpen()))
return false;
#if defined(CN_COMM_FOR_CE)
::SetupComm(hComm_, 4096, 4096);
#else
if(!CN_ASSERT(::SetupComm(hComm_, 4096, 4096)))//! <20><><EFBFBD>ö˿ڷ<CBBF><DAB7>ͽ<EFBFBD><CDBD>ն<EFBFBD><D5B6>д<EFBFBD>С, <20><>4096<39>ֽ<EFBFBD>, д4096<39>ֽ<EFBFBD>, <20><><EFBFBD><EFBFBD>I/Oģʽ<C4A3><CABD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return false;
#endif
if(!CN_ASSERT(::GetCommTimeouts(hComm_, &CO_)))
return false;
CO_.ReadIntervalTimeout = 50;//! <20><><EFBFBD>ó<EFBFBD>ʱ<EFBFBD><20>ַ<EFBFBD><D6B7><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>100ms
CO_.ReadTotalTimeoutMultiplier = 0;
CO_.ReadTotalTimeoutConstant = IsOverlappedMode() ? 500 : m_lReadTimeout;//! <20><><EFBFBD><EFBFBD>ʱ <20>ص<EFBFBD>I/Oģʽ<C4A3><CABD>500<30><30><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>I/Oģʽ<C4A3><CABD>250<35><30><EFBFBD><EFBFBD>
CO_.WriteTotalTimeoutMultiplier = IsOverlappedMode() ? 1 : 0;
CO_.WriteTotalTimeoutConstant = IsOverlappedMode() ? 10000 : 250;//! д<><D0B4>ʱ <20>ص<EFBFBD>I/Oģʽ<C4A3><CABD>(10000+1<><31><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>)<29><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>I/Oģʽ<C4A3><CABD>250<35><30><EFBFBD><EFBFBD>
if(!CN_ASSERT(::SetCommTimeouts(hComm_, &CO_)))
return false;
if(!CN_ASSERT(::PurgeComm(hComm_, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR )))//! <20><><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD>
return false;
return true;
}
//! <20><><EFBFBD>˿<EFBFBD><CBBF><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD><EBBBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DWORD PortToBuffer(DWORD dwPortByteNum)
{
BlockBuffer::InnerLock locker(&I_);
return dwPortByteNum ? I_.Release(ReadPort(I_.GetFreePtr(dwPortByteNum), dwPortByteNum)) : 0;
}
//! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>˿<EFBFBD>
DWORD BufferToPort(DWORD dwMaxSize = 1024)
{
if (IsOverlappedMode())
{
BlockBuffer::InnerLock locker(&O_);
if (!O_.Size())
return 0;
DWORD dwWrite = dwMaxSize > O_.GetPtrSize() ? O_.GetPtrSize() : dwMaxSize;
WritePort(O_.GetPtr(), dwWrite);
return O_.Read(NULL, dwWrite);
}
else
{
BYTE btTemp[1024];
DWORD dwLength, dwIndex = 0;
O_.Lock();
dwLength = O_.Read(btTemp, 1024);
O_.Unlock();
while ( dwIndex < dwLength )
dwIndex += WritePort(btTemp + dwIndex, dwLength - dwIndex);
return dwLength;
}
}
/*! \param uMsg <20><>Ϣ \param lParam <20><><EFBFBD><EFBFBD> \param bPostMode <20><><EFBFBD><EFBFBD>PostMessage<67><65><EFBFBD><EFBFBD>SendMessage<67><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ*/
//! <20><><EFBFBD><EFBFBD><EFBFBD>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ID<49><44>Ч, <20>ͳ<EFBFBD><CDB3><EFBFBD>Ϣ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>¼<EFBFBD>֪ͨ, WPARAMĬ<4D>ϰ<EFBFBD><CFB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>
virtual void Notify(UINT uMsg, LPARAM lParam = 0, bool bPostMode = true)
{
if (NULL != m_pComCb)
m_pComCb(uMsg, m_pUser);
else if (m_pfn != nullptr)
m_pfn();
}
//---------------------------------------threads callback-----------------------------------------------------
//! <20><>ӦEV_RXCHAR<41>¼<EFBFBD> <20><><EFBFBD>̻߳ص<CCBB>, <20><EFBFBD><E9BAAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ(<28>Ƽ<EFBFBD><C6BC><EFBFBD>ʽ)
virtual void OnReceive()
{
Notify(ON_COM_RECEIVE);
}
//! <20><>ӦEV_DSR<53>¼<EFBFBD>
virtual void OnDSR()
{
Notify(ON_COM_DSR, CheckDSR() ? 1 : 0);
}
//! <20><>ӦEV_CTS<54>¼<EFBFBD>
virtual void OnCTS()
{
Notify(ON_COM_CTS, CheckCTS() ? 1 : 0);
}
//! <20><>ӦEV_BREAK<41>¼<EFBFBD>
virtual void OnBreak()
{
ClearCommBreak(hComm_);
Notify(ON_COM_BREAK);
}
//! <20><>ӦEV_TXEMPTY<54>¼<EFBFBD>
virtual void OnTxEmpty()
{
Notify(ON_COM_TXEMPTY);
}
//! <20><>ӦEV_ERROR<4F>¼<EFBFBD>
virtual void OnError()
{
Notify(ON_COM_ERROR, ClearError());
}
//! <20><>ӦEV_RING<4E>¼<EFBFBD>
virtual void OnRing()
{
Notify(ON_COM_RING, CheckRING() ? 1 : 0);
}
//! <20><>ӦEV_RLSD<53>¼<EFBFBD>
virtual void OnRLSD()
{
Notify(MS_RLSD_ON, CheckRLSD() ? 1 : 0);
}
//! <20><>ӦEV_RXFLAG<41>¼<EFBFBD>
virtual void OnRxFlag()
{
Notify(ON_COM_RXFLAG);
}
//! <20><>ӦEV_POWER<45>¼<EFBFBD>
virtual void OnPower()
{
Notify(ON_COM_POWER);
}
//! <20><>ӦEV_RX80FULL<4C>¼<EFBFBD>
virtual void OnRx80Full()
{
Notify(ON_COM_RX80FULL);
}
//! <20><>ӦEV_EVENT1<54>¼<EFBFBD>
virtual void OnEvent1()
{
Notify(ON_COM_EVENT1);
}
//! <20><>ӦEV_EVENT2<54>¼<EFBFBD>
virtual void OnEvent2()
{
Notify(ON_COM_EVENT2);
}
//! <20><>ӦEV_PERR<52>¼<EFBFBD>
virtual void OnPrintErr()
{
Notify(ON_COM_PERR);
}
//! ͨ<>õ<EFBFBD><C3B5>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>
virtual void HandleEvent(DWORD dwMask)
{
if ((dwMask & EV_RXCHAR) && !(dwOption_&EN_RX_THREAD))
{
DWORD dwLength = GetQueueCount(true);
if (dwLength)
{
if (dwOption_ & EN_RX_BUFFER)
{
PortToBuffer((dwLength << 1) + 64);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>϶<EFBFBD><CFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (I_.Size() >= dwNotifyNum_)
OnReceive();
}
else
{
if (dwLength >= dwNotifyNum_)
OnReceive();
}
}
}
if (dwMask & EV_TXEMPTY)
{
if ((dwOption_&EN_TX_BUFFER) && !(dwOption_&EN_TX_THREAD) && O_.SafeSize())
BufferToPort();
OnTxEmpty();
}
if (dwMask & EV_RXFLAG)
OnRxFlag();
if (dwMask & EV_CTS)
OnCTS();
if (dwMask & EV_DSR)
OnDSR();
if (dwMask & EV_RING)
OnRing();
if (dwMask & EV_RLSD)
OnRLSD();
if (dwMask & EV_BREAK)
OnBreak();
if (dwMask & EV_ERR)
OnError();
#ifdef CN_COMM_FOR_CE
if (dwMask & EV_POWER)
OnPower();
#endif
}
#ifndef CN_COMM_FOR_CE
//! <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>I/Oģ<4F><C4A3>
virtual DWORD OverlappedModel()
{
if(!CN_ASSERT(IsOpen()))
return 1;
if(!CN_ASSERT(::SetCommMask(hComm_, dwWaitEvent_)))
return 1;
for(DWORD dwMask = 0, dwLength; bContinue_ && IsOpen(); dwMask = 0)
{
if (GetQueueCount(true))//! <20>ȴ<EFBFBD><C8B4>¼<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>һ<EFBFBD><D2BB>EV_RXCHAR<41>¼<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
dwMask = EV_RXCHAR, Sleep(10);
else
{
if(!::WaitCommEvent(hComm_, &dwMask, &EO_))
{
if(::GetLastError() == ERROR_IO_PENDING)
::GetOverlappedResult(hComm_, &EO_, &dwLength, TRUE);
else
{
Sleep(10);
continue;
}
}
}
if(dwMask == 0)
{
if ((dwOption_&EN_TX_BUFFER) && !(dwOption_&EN_TX_THREAD) && O_.SafeSize())
BufferToPort();
continue;
}
HandleEvent(dwMask);
}//for
return 0;
}
#endif
//! <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I/Oģ<4F><C4A3>
virtual DWORD NonoverlappedModel()
{
if(!CN_ASSERT(IsOpen()))
return 1;
for (DWORD dwReturn; bContinue_ && IsOpen();)
{
dwReturn = WaitForSingleObject(hWatchEvent_, 50);
if (!bContinue_)
break;
switch (dwReturn)
{
case WAIT_OBJECT_0:
while ((dwOption_&EN_TX_BUFFER) && O_.SafeSize())
BufferToPort();
ResetEvent(hWatchEvent_);
break;
case WAIT_TIMEOUT:
DWORD dwLength = GetQueueCount(true);
if (dwLength)
{
if (dwOption_ & EN_RX_BUFFER)
{
PortToBuffer(dwLength);
if (I_.Size() >= dwNotifyNum_)
OnReceive();
}
else
{
if (dwLength >= dwNotifyNum_)
OnReceive();
}
}
if ( (dwOption_&EN_TX_BUFFER) && O_.SafeSize() )
BufferToPort();
break;
}
}
return 0;
}
#ifdef CN_COMM_FOR_CE
//! <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD>WINCE<43><45>I/Oģ<4F><C4A3>(<28>ص<EFBFBD>+<2B><><EFBFBD><EFBFBD> Ҳ<><D2B2>֪΢<D6AA><CEA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲôģʽ)
virtual DWORD EmbeddedModel()
{
if(!CN_ASSERT(IsOpen()))
return 1;
if(!CN_ASSERT(::SetCommMask(hComm_, dwWaitEvent_)))
return 1;
for(DWORD dwMask = 0; bContinue_ && IsOpen(); dwMask = 0)
{
if (GetQueueCount(true))//! <20>ȴ<EFBFBD><C8B4>¼<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>һ<EFBFBD><D2BB>EV_RXCHAR<41>¼<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
dwMask = EV_RXCHAR, Sleep(10);
else
{
if(!::WaitCommEvent(hComm_, &dwMask, NULL))
continue;
}
if(dwMask == 0)
{
if ( (dwOption_&EN_TX_BUFFER) && !(dwOption_&EN_TX_THREAD) && O_.SafeSize())
BufferToPort();
continue;
}
HandleEvent(dwMask);
}//for
return 0;
}
#endif
//! <20><><EFBFBD><EFBFBD>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD>Ըı<D4B8><C4B1><EFBFBD>;
virtual DWORD ReadModel()
{
while(bContinue_)
{
Sleep(50);
DWORD dwLength = GetQueueCount(true);
if (dwLength)
{
if (dwOption_ & EN_RX_BUFFER)
{
PortToBuffer(dwLength);
if (I_.Size() >= dwNotifyNum_)
OnReceive();
}
else
{
if (dwLength >= dwNotifyNum_)
OnReceive();
}
}
}
return 0;
}
//! <20><><EFBFBD><EFBFBD>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD>Ըı<D4B8><C4B1><EFBFBD>;
virtual DWORD WriteModel()
{
if (!IsOpen())
{
return -1;
}
CN_ASSERT(dwOption_ & EN_TX_BUFFER);
while (bContinue_)
{
DWORD dwReturn = ::WaitForSingleObject(hWriteEvent_, 200);
while(bContinue_ && O_.SafeSize())
BufferToPort();
if (dwReturn == WAIT_OBJECT_0)
ResetEvent(hWatchEvent_);
}
return 0;
}
private:
//! <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ComComm(const ComComm&);
//! <20><>ֹ<EFBFBD><D6B9>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>
ComComm &operator = (const ComComm&);
#if defined(_MT) && !defined(CN_COMM_FOR_CE)
//! <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> Watch MyThread <20><><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><C3BE><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ɶ<EFBFBD>д
static UINT APIENTRY WatchThreadProc(LPVOID lpPara)
#else
//! <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> Watch MyThread <20><><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><C3BE><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ɶ<EFBFBD>д
static DWORD WINAPI WatchThreadProc(LPVOID lpPara)
#endif
{
#ifdef CN_COMM_FOR_CE
DWORD dwCode = ((ComComm *)lpPara)->EmbeddedModel();
#else
DWORD dwCode = ((ComComm *)lpPara)->IsOverlappedMode()
? ((ComComm *)lpPara)->OverlappedModel()
: ((ComComm *)lpPara)->NonoverlappedModel();
#if defined(_MT)
_endthreadex(dwCode);
#endif
#endif
return dwCode;
}
#if defined(_MT) && !defined(CN_COMM_FOR_CE)
//! ˫<><CBAB><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> <20><>ʱδ<CAB1><CEB4> <20><><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
static UINT APIENTRY ReadThreadProc(LPVOID lpPara)
#else
//! ˫<><CBAB><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> <20><>ʱδ<CAB1><CEB4> <20><><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
static DWORD WINAPI ReadThreadProc(LPVOID lpPara)
#endif
{
DWORD dwCode = ((ComComm *)lpPara)->ReadModel();
#if defined(_MT) && !defined(CN_COMM_FOR_CE)
_endthreadex(dwCode);
#endif
return dwCode;
}
#if defined(_MT) && !defined(CN_COMM_FOR_CE)
//! ˫<><CBAB><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> WINCE<43><45><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD>
static UINT APIENTRY WriteThreadProc(LPVOID lpPara)
#else
//! ˫<><CBAB><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD> WINCE<43><45><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD>
static DWORD WINAPI WriteThreadProc(LPVOID lpPara)
#endif
{
DWORD dwCode = ((ComComm *)lpPara)->WriteModel();
#if defined(_MT) && !defined(CN_COMM_FOR_CE)
_endthreadex(dwCode);
#endif
return dwCode;
}
};
#endif //! _CN_COMM_H_