3,881
社区成员
发帖
与我相关
我的任务
分享
//.h
#pragma once
/*
* Copyright (c) 2011,431工作室
* All rights reserved.
*
* 文件名称:Comm.h
* 摘 要:与卡交互底层类(public函数,供AdvancedComm.h封装应用,不要直接在其它地方使用)
*
* 当前版本:1.1
* 作 者:431
* 完成日期:2011年7月29日
*
* 取代版本:1.0
* 原作者 :431
* 完成日期:2011年7月28日
*/
#include <vector>
using namespace std;
//AT命令返回信息
enum CommandResultType {
COMMAND_OK,
COMMAND_UNKNOWN_ERROR,
COMMAND_DATA_NOT_FOUND,
COMMAND_OPENPORT_FAIL,
COMMAND_WRITE_FAIL
};
//AT命令读缓冲区尺寸
const int AT_BUFFER_SIZE = 128;
class CComm
{
public:
CComm(void);
public:
~CComm(void);
private:
BOOL GetConfigIni(vector<CString> &vec); //读配置文件COM名称列表
DWORD GetAvailableDataLen(); //获取字节流长度
BOOL Read(void* pBuf, DWORD dwBufLen, DWORD& dwDataLen); //读buffer数据
BOOL Write(const void* pData, DWORD dwDataLen); //写buffer数据
public:
BOOL QueryPCUIPort(long int& dwPortNum); //查找PCUI设备口
BOOL Open(long int dwPortNum); //打开指定COM口
void Close(); //关闭COM口
CommandResultType ExecuteATCommand(char* pCmd, char* pResult); //发送AT指令
private:
vector<CString> m_cfgPorts; //配置文件COM名称列表
};
//.cpp
#include "StdAfx.h"
#include "Comm.h"
#include <Setupapi.h> //在“Demo 属性页-》配置属性-》链接器-》输入-》附加依赖项”增加setupapi.lib。
#include "GlobalFunction.h"
static HANDLE m_hComHandle = INVALID_HANDLE_VALUE; //加static,说明这个变量只类内使用
CComm::CComm(void)
{
GetConfigIni(m_cfgPorts);
}
CComm::~CComm(void)
{
}
/*
* 函数介绍: 读配置文件COM名称列表
* 输入参数: 无
* 输出参数: vec,COM名称列表
* 返回值 : TRUE,配置文件找到;FALSE,配置文件没找到
*/
BOOL CComm::GetConfigIni(vector<CString> &vec)
{
vec.clear();
wstring wstrWorkDir = CGlobalFunction::GetModuleDirectory();
string strWorkDir = CGlobalFunction::WideCharToMultiByte(wstrWorkDir.c_str(), 0);
CString cstrWorkDir = CString(strWorkDir.c_str());
CString cstrPortSettingFile = cstrWorkDir + _T("config.ini");
vec.clear();
for (int i=0; i<255; i++)
{
CString cstrPortNum = "";
CString cstrPortName = "";
cstrPortNum.Format(_T("port%d"), i+1);
//if (GetKeyValue(cstrPortSettingFile, "PORT", cstrPortNum, cstrPortName))
{
//vec.push_back(cstrPortName);
vec.push_back("HUAWEI Mobile CMCC AT Interface");
}
//else
{
break;
}
}
return TRUE;
}
/*
* 函数介绍: 查找PCUI设备口
* 输入参数: 无
* 输出参数: dwPortNum,COM口号
* 返回值 : TRUE,找到COM口;FALSE,没找到COM口
*/
BOOL CComm::QueryPCUIPort(long int& dwPortNum)
{
HDEVINFO NewDeviceInfoSet;
SP_DEVINFO_DATA DeviceInfoData;
DWORD PropertyRegDataType;
BYTE PropertyBuffer[1024];
DWORD RequiredSize;
BOOL bDev, bDrv;
int i = 0;
BOOL Result = FALSE;
GUID Guid = {0x4d36e978L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
do
{
NewDeviceInfoSet = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE == NewDeviceInfoSet)
{
return Result;
}
bDev = FALSE;
bDrv = FALSE;
memset(&DeviceInfoData, 0, sizeof(DeviceInfoData));
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
bDev = SetupDiEnumDeviceInfo(NewDeviceInfoSet, i, &DeviceInfoData);
if (bDev)
{
memset(PropertyBuffer, 0, 1024);
bDrv = SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet, &DeviceInfoData,
SPDRP_FRIENDLYNAME, &PropertyRegDataType, PropertyBuffer, 1024, &RequiredSize);
if (bDrv)
{
char* cPorts;
vector<CString>::iterator iter = m_cfgPorts.begin();
for (iter=m_cfgPorts.begin(); iter!=m_cfgPorts.end(); iter++)
{
if ((strstr((const char*)PropertyBuffer, (*iter).GetBuffer()) != NULL)
&& (cPorts=const_cast<char*>(strstr((const char*)PropertyBuffer, "COM"))))
{
dwPortNum = (DWORD)atol((char*)&cPorts[3]);
Result = TRUE;
break;
}
}
if (Result)
{
break;
}
}
}
else
{
DWORD dwError = GetLastError();
if ((ERROR_SUCCESS==dwError) | (ERROR_NO_MORE_ITEMS==dwError))
{
break;
}
}
Sleep(500);
i++;
}
while (true);
SetupDiDestroyDeviceInfoList(NewDeviceInfoSet);
return Result;
}
/*
* 函数介绍: 打开指定COM口
* 输入参数: dwPortNum,COM口号
* 输出参数: 无
* 返回值 : TRUE,成功打开COM口;FALSE,打开COM口失败。
*/
BOOL CComm::Open(long int dwPortNum)
{
CString str;
std::string strPortName;
str.Format("\\\\.\\COM%d", dwPortNum);
strPortName = str;
m_hComHandle = CreateFile(strPortName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == m_hComHandle)
{
return FALSE;
}
SetCommMask(m_hComHandle, EV_RXCHAR);
DCB dcb;
if (!GetCommState(m_hComHandle, &dcb))
{
CloseHandle(m_hComHandle);
m_hComHandle = INVALID_HANDLE_VALUE;
return FALSE;
}
dcb.BaudRate = CBR_115200;
dcb.Parity = NOPARITY;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.fDsrSensitivity = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
if (!SetCommState(m_hComHandle, &dcb))
{
CloseHandle(m_hComHandle);
m_hComHandle = INVALID_HANDLE_VALUE;
return FALSE;
}
return TRUE;
}
/*
* 函数介绍: 关闭COM口
* 输入参数: 无
* 输出参数: 无
* 返回值 : 无
*/
void CComm::Close()
{
if (INVALID_HANDLE_VALUE != m_hComHandle)
{
CloseHandle(m_hComHandle);
}
m_hComHandle = INVALID_HANDLE_VALUE;
}
/*
* 函数介绍: 获取字节流长度
* 输入参数: 无
* 输出参数: 无
* 返回值 : 字节流长
*/
DWORD CComm::GetAvailableDataLen()
{
COMSTAT ComState;
DWORD dwError;
if (!ClearCommError(m_hComHandle, &dwError, &ComState))
{
return 0;
}
return ComState.cbInQue;
}
/*
* 函数介绍: 读buffer数据
* 输入参数: 无
* 输出参数: pBuf,缓冲区;dwBufLen,缓冲区大小;dwDataLen,数据长度
* 返回值 : TRUE,读成功;FALSE,读失败。
*/
BOOL CComm::Read(void* pBuf, DWORD dwBufLen, DWORD& dwDataLen)
{
if (INVALID_HANDLE_VALUE == m_hComHandle)
{
return FALSE;
}
DWORD dwDataInCom = 0;
BYTE* pRetBuf = (BYTE*)pBuf;
dwDataLen = 0;
dwDataInCom = GetAvailableDataLen();
OVERLAPPED* pOverLap = new OVERLAPPED;
BOOL bRet = FALSE;
memset(pOverLap, 0, sizeof(OVERLAPPED));
pOverLap->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
try
{
bRet = ReadFile(m_hComHandle, pBuf, dwBufLen, &dwDataLen, pOverLap);
}
catch (...)
{
dwDataLen = 0;
CloseHandle(pOverLap->hEvent);
return FALSE;
}
if (FALSE == bRet)
{
DWORD dwError = GetLastError();
if(ERROR_IO_PENDING == dwError)
{
DWORD dwState = WaitForSingleObject(pOverLap->hEvent, 500);
switch (dwState)
{
case WAIT_OBJECT_0:
{
if (GetOverlappedResult(m_hComHandle, pOverLap, &dwDataInCom, FALSE))
{
bRet = TRUE;
dwDataLen = (DWORD)pOverLap->InternalHigh; //强转,获取数据长度
}
}
break;
case WAIT_TIMEOUT:
break;
default:
break;
}
}
}
else
{
bRet = TRUE;
dwDataLen = (DWORD)pOverLap->InternalHigh; //强转,获取数据长度
}
CloseHandle(pOverLap->hEvent);
return bRet;
}
/*
* 函数介绍: 写buffer数据
* 输入参数: pData,缓冲区;dwDataLen,缓冲区大小
* 输出参数: 无
* 返回值 : TRUE,写成功;FALSE,写失败。
*/
BOOL CComm::Write(const void* pData, DWORD dwDataLen)
{
DWORD dwWriteLen;
OVERLAPPED OverLap;
memset(&OverLap, 0, sizeof(OverLap));
if (INVALID_HANDLE_VALUE == m_hComHandle)
{
return FALSE;
}
OverLap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
BOOL bRet = FALSE;
try
{
bRet = WriteFile(m_hComHandle, pData, dwDataLen, &dwWriteLen, &OverLap);
}
catch(...)
{
dwWriteLen = 0;
CloseHandle(OverLap.hEvent);
return FALSE;
}
if (!bRet)
{
if (ERROR_IO_PENDING == GetLastError())
{
DWORD dwState = WaitForSingleObject(OverLap.hEvent, 2000);
switch (dwState)
{
case WAIT_OBJECT_0:
{
if (GetOverlappedResult(m_hComHandle, &OverLap, &dwWriteLen, FALSE))
{
if (dwWriteLen == dwDataLen)
{
bRet = TRUE;
}
}
}
break;
case WAIT_TIMEOUT:
break;
default:
break;
}
}
else
{
if (dwDataLen == (DWORD)OverLap.InternalHigh) //强转,获取数据长度
{
bRet = TRUE;
}
}
}
CloseHandle(OverLap.hEvent);
return bRet;
}
/*
* 函数介绍: 发送AT指令
* 输入参数: pCmd,AT指令
* 输出参数: pResult,返回数据
* 返回值 : 枚举结果信息
*/
CommandResultType CComm::ExecuteATCommand(char* pCmd, char* pResult)
{
if (NULL == pResult)
{
return COMMAND_UNKNOWN_ERROR;
}
char ans[AT_BUFFER_SIZE] = {0};
if (!Write(pCmd, (DWORD)strlen(pCmd))) //强转,获取数据长度
{
return COMMAND_WRITE_FAIL;
}
DWORD dwStart = GetTickCount();
BOOL get_response = FALSE;
while (GetTickCount() - dwStart < 3000)
{
DWORD dwDataLen;
Read(ans, AT_BUFFER_SIZE, dwDataLen);
if (strstr(ans, "OK") != NULL)
{
get_response = TRUE;
strcpy(pResult, ans);
return COMMAND_OK;
}
else if (strstr(ans, "ERROR") != NULL)
{
return COMMAND_UNKNOWN_ERROR;
}
else if (strstr(ans, "COMMAND NOT SUPPORTED") != NULL)
{
return COMMAND_UNKNOWN_ERROR;
}
else
{
Sleep(500);
}
}
if (!get_response)
{
return COMMAND_UNKNOWN_ERROR;
}
strcpy(pResult, ans);
return COMMAND_OK;
}
//.h
#pragma once
/*
* Copyright (c) 2011,431工作室
* All rights reserved.
*
* 文件名称:AdvancedComm.h
* 摘 要:与数据卡交互高层封装函数(供外部使用)
*
* 当前版本:1.1
* 作 者:431
* 完成日期:2011年7月29日
*
* 取代版本:1.0
* 原作者 :431
* 完成日期:2011年7月28日
*/
#include "Comm.h"
BOOL ExecuteCommand(CString cstrCommand, long int dwPortnum, CommandResultType& cmdResult); //发送命令到指定端口
CommandResultType IsDataCardValid(long int& dwPortnum); //检测数据卡有效性
CommandResultType getSN(long int& dwPortnum, CString &strInfo); //获取SN号
//.cpp
#include "StdAfx.h"
#include "AdvancedComm.h"
/*
* 函数介绍: 发送命令到指定端口(此函数,只供内部调用)
* 输入参数: cstrCommand,AT命令;dwPortnum,端口号
* 输出参数: cmdResult,枚举结果信息
* 返回值 : TRUE,AT命令成功响应;FALSE,AT命令失败响应
*/
BOOL ExecuteCommand(CString cstrCommand, long int dwPortnum, CommandResultType& cmdResult)
{
cstrCommand += "\r";
CComm comm;
char buffer[AT_BUFFER_SIZE] = {0};
if (!comm.Open(dwPortnum))
{
cmdResult = COMMAND_OPENPORT_FAIL;
return FALSE;
}
cmdResult = comm.ExecuteATCommand(cstrCommand.GetBuffer(0), buffer);
comm.Close();
if (COMMAND_OK == cmdResult)
{
return TRUE;
}
else
{
return FALSE;
}
return FALSE;
}
/*
* 函数介绍: 检测数据卡有效性
* 输入参数: dwPortnum,端口号
* 输出参数: 无
* 返回值 : 枚举结果信息
*/
CommandResultType IsDataCardValid(long int& dwPortnum)
{
CComm comm;
if (!comm.QueryPCUIPort(dwPortnum))
{
return COMMAND_DATA_NOT_FOUND;
}
if (!comm.Open(dwPortnum))
{
return COMMAND_OPENPORT_FAIL;
}
comm.Close();
CommandResultType cmdResult;
ExecuteCommand("AT", dwPortnum, cmdResult);
return cmdResult;
}
/*
* 函数介绍: 获取SN号
* 输入参数: dwPortnum,端口号
* 输出参数: strInfo,SN号
* 返回值 : 枚举结果信息
*/
CommandResultType getSN(long int& dwPortnum, CString &strInfo)
{
CComm comm;
if (!comm.Open(dwPortnum))
{
return COMMAND_OPENPORT_FAIL;
}
comm.Close();
CommandResultType cmdResult;
ExecuteCommand("AT^SN", dwPortnum, cmdResult);
return cmdResult;
}