#pragma once
#include "MsGlobal.h"
#include <windows.h>
#include <process.h>
#include "hid/hidapi.h"
#pragma comment (lib,"setupapi.lib")
using namespace std;
struct sBuff {
sBuff() {
stop = 0;
len = 0;
memset(udata, 0, 10240);
}
int stop;
int len;
unsigned char udata[10240];
};
class ComBase
{
public:
ComBase();
~ComBase();
int InitUSB(unsigned short vid, unsigned short pid);
int OpenUSB(unsigned short vid, unsigned short pid);
void CloseUSB();
public:
int SendMsg(unsigned char* Send, size_t nLength);
int ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength);
int getDevStatus() { return handle ? 0 : 1; }
hid_device *getHID() { return this->handle; }
sBuff *getBuff() { return this->m_pBuff; }
void setBuff(sBuff *pBuff) { this->m_pBuff = pBuff; }
private:
hid_device *handle;
sBuff *m_pBuff;
};
#include "ComBase.h"
#include "algorithm/GCS_Encrypt.h"
#include "files/logFile.h"
ComBase::ComBase()
{
handle = nullptr;
m_pBuff = new sBuff();
}
ComBase::~ComBase()
{
if (handle)
CloseUSB();
delete m_pBuff;
m_pBuff = nullptr;
}
int ComBase::InitUSB(unsigned short vid, unsigned short pid)
{
if (hid_init())//实际上不调用它hid_enumerate和下面的hid_open也会自动调用
return -1;
hid_device_info* Hids, *HidsCopy;//一个用于接收设备信息的单链表,另一个用来遍历,该结构体使用unicode编码,所以下面都要用unicode处理方式
Hids = hid_enumerate(vid, pid);//获取vid为0x154F,pid为0x4304的HID设备链表,这里如果都是0就是获取所有的HID设备
HidsCopy = Hids;
LPCWSTR wpSerialNumber = L"\0";//用来去重,一个hid设备一般有多个端点,因此会读到多个
while (HidsCopy)
{
if (CompareStringW(LOCALE_INVARIANT, NORM_LINGUISTIC_CASING, wpSerialNumber, -1, HidsCopy->serial_number, -1) != CSTR_EQUAL)//去重
{
xPrintf((LPCTSTR)HidsCopy->serial_number);
wpSerialNumber = HidsCopy->serial_number;//我这里只需要序列号,实际上这个结构体还有很多数据,可以参考官方的实例
}
HidsCopy = HidsCopy->next;
}
hid_free_enumeration(Hids);//释放设备链表
return 0;
}
/*********************************************************
函数名称: OpenUSB(LPCTSTR PscSerialNumber)
函数功能: 打开USB-HID设备
输入参数:
参数1: LPCTSTR PscSerialNumber - HID设备的序列号
返回值:
成功 - 0
失败 - -1
********************************************************/
int ComBase::OpenUSB(unsigned short vid, unsigned short pid)
{
if (MsGlobal::m_VirtualVer == VER_VIRTUAL) {
return 0;
}
if (handle)
CloseUSB();
handle = hid_open(vid, pid, NULL);//打开指定vid、pid、序列号的设备
if (!handle)
{
xPrintf("无法打开USB设备");
hid_exit();
return -1;
}
// 将hid_read()函数设置为非阻塞。
if (hid_set_nonblocking(handle, 1) != 0)// 1启用非阻塞 0禁用非阻塞。
{
xPrintf("设置非阻塞失败");
hid_close(handle);
hid_exit();
return -2;
}
return 0;
}
//关闭USB-HID设备
/*********************************************************
函数名称: CloseUSB(hid_device*& handle)
函数功能: 关闭USB-HID设备
输入参数:
参数1: hid_device*& handle - 操作句柄
********************************************************/
void ComBase::CloseUSB()
{
if (MsGlobal::m_VirtualVer == VER_VIRTUAL) {
return;
}
if (handle)
{
hid_close(handle);
hid_exit();
}
handle = nullptr;//这里将指针置空,增强安全性
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// 线程执行的函数
unsigned int WINAPI ThreadSendMsg(LPVOID lpThreadParameter)
{
ComBase *m_pDev = (ComBase *)lpThreadParameter;
if (!m_pDev) {
xPrintf("lpThreadParameter error");
return -1;
}
sBuff *pBuff = m_pDev->getBuff();
if (!pBuff || pBuff->len == 0) {
xPrintf("getBuff error");
return -2;
}
hid_device *handle = m_pDev->getHID();
if (handle == INVALID_HANDLE_VALUE) {
xPrintf("getHID error");
return -3;
}
// 读取数据并清空缓存
int leftNum = 1;
while (leftNum)
{
unsigned char buf[1024];
memset(buf, 0, 1024);
leftNum = hid_read_timeout(handle, buf, sizeof(buf), 0);
if (leftNum < 0) {
xPrintf("hid_read_timeout error");
return -4;
}
}
// 此处对消息进行加密,从第三个字节开始
GCS_Msg_Encryption(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]);
// 此处分包,目前支持64个字节(加上id一共65个字节)
int size = 64;
int packs = pBuff->len / size * size;
if (pBuff->len % size != 0)
{
packs++;
}
int result = 0;
for (int i = 0; i < packs; i++)
{
int rlen = size;
if (i * size > pBuff->len)
rlen = pBuff->len - (i - 1) * size;
UCHAR OutputReport[65];
memset(OutputReport, 0, 65);
memcpy(&OutputReport[1], &pBuff->udata[i * size], rlen);
int iResp = hid_write(handle, OutputReport, 65);
if (iResp < 0) {
xPrintf("hid_write error");
result = -5;
break;
}
}
ExitThread(result);
}
int ComBase::SendMsg(unsigned char* Send, size_t nLength)
{
/// 初始化缓存
this->m_pBuff->stop = 0;
this->m_pBuff->len = nLength;
memcpy(this->m_pBuff->udata, Send, nLength);
/// 启动发送线程
unsigned int dwThreadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadSendMsg, (void *)this, 0, &dwThreadID);
if (hThread == NULL) {
xPrintf("_beginthreadex Error!");
return -1;
}
/// 线程阻塞
DWORD wr = WaitForSingleObject(hThread, 3000);
switch (wr)
{
case WAIT_FAILED:
{
xPrintf("thread wait failed");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -2;
}
break;
case WAIT_TIMEOUT:
{
xPrintf("thread wait timeout");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -3;
}
break;
default:
break;
}
/// 获取线程函数的返回值
DWORD dwExitCode;
GetExitCodeThread(hThread, &dwExitCode);
if (dwExitCode != 0)
{
xPrintf("thread exit code error");
CloseHandle(hThread);
return -4;
}
CloseHandle(hThread);
return 0;
}
// 线程执行的函数
unsigned int WINAPI ThreadReceiveMsg(LPVOID lpThreadParameter)
{
ComBase *m_pDev = (ComBase *)lpThreadParameter;
if (!m_pDev) {
xPrintf("lpThreadParameter error");
return -1;
}
sBuff *pBuff = m_pDev->getBuff();
if (!pBuff || pBuff->len != 0) {
xPrintf("getBuff error");
return -2;
}
hid_device *handle = m_pDev->getHID();
if (handle == INVALID_HANDLE_VALUE) {
xPrintf("getHID error");
return -3;
}
int result = 0;
while (!pBuff->stop)
{
UCHAR recvDataBuf[1024];
memset(recvDataBuf, 0, 1024);
int len = hid_read(handle, recvDataBuf, 65);
if (len > 0)
{
memcpy(&pBuff->udata[pBuff->len], recvDataBuf, len);
pBuff->len += len;
if (pBuff->udata[0] != 0xE5)
{/// 无效数据
xPrintf("read data exception\n");
result = -4;
break;
}
else
{/// 有效数据
int msglen = pBuff->udata[1] + 2;
if (msglen <= pBuff->len)
{/// 接收完成
// 此处对消息进行解密,从第三个字节开始
GCS_Msg_Decrypt(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]);
//计算crc16
uint16_t crc = crc16_modbus(&pBuff->udata[0], msglen - 2);
uint8_t crc_low = crc & 0xFF;
uint8_t crc_high = (crc >> 8) & 0xFF;
if (crc_low != pBuff->udata[msglen - 1] ||
crc_high != pBuff->udata[msglen - 2])
{
xPrintf("crc error\n");
result = -5;
break;
}
else
{
xPrintf("read data finish\n");
result = 0;
break;
}
}
else
{/// 接收未完成
xPrintf("read data unfinish\n");
continue;
}
}
}
}
ExitThread(result);
}
int ComBase::ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength)
{
/// 刷新缓存
this->m_pBuff->stop = 0;
this->m_pBuff->len = 0;
memset(this->m_pBuff->udata, 0, 10240);
/// 启动接收线程
unsigned int dwThreadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadReceiveMsg, (void *)this, 0, &dwThreadID);
if (hThread == NULL) {
xPrintf("_beginthreadex error!");
return -1;
}
/// 线程阻塞
DWORD wr = WaitForSingleObject(hThread, 3000);
switch (wr)
{
case WAIT_FAILED:
{
xPrintf("thread wait failed");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -2;
}
break;
case WAIT_TIMEOUT:
{
xPrintf("thread wait timeout");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -3;
}
break;
default:
break;
}
/// 获取线程函数的返回值
DWORD dwExitCode;
GetExitCodeThread(hThread, &dwExitCode);
if (dwExitCode != 0)
{
xPrintf("thread exit code error");
CloseHandle(hThread);
return -4;
}
/// 根据协议拷贝有效的消息部分
nLength = this->m_pBuff->udata[1] + 2;
memcpy(pReceiveBuf, this->m_pBuff->udata, nLength);
CloseHandle(hThread);
return 0;
}#pragma once
#include "MsGlobal.h"
#include <windows.h>
#include <process.h>
#include "hid/hidapi.h"
#pragma comment (lib,"setupapi.lib")
using namespace std;
struct sBuff {
sBuff() {
stop = 0;
len = 0;
memset(udata, 0, 10240);
}
int stop;
int len;
unsigned char udata[10240];
};
class ComBase
{
public:
ComBase();
~ComBase();
int InitUSB(unsigned short vid, unsigned short pid);
int OpenUSB(unsigned short vid, unsigned short pid);
void CloseUSB();
public:
int SendMsg(unsigned char* Send, size_t nLength);
int ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength);
int getDevStatus() { return handle ? 0 : 1; }
hid_device *getHID() { return this->handle; }
sBuff *getBuff() { return this->m_pBuff; }
void setBuff(sBuff *pBuff) { this->m_pBuff = pBuff; }
private:
hid_device *handle;
sBuff *m_pBuff;
};
#include "ComBase.h"
#include "algorithm/GCS_Encrypt.h"
#include "files/logFile.h"
ComBase::ComBase()
{
handle = nullptr;
m_pBuff = new sBuff();
}
ComBase::~ComBase()
{
if (handle)
CloseUSB();
delete m_pBuff;
m_pBuff = nullptr;
}
int ComBase::InitUSB(unsigned short vid, unsigned short pid)
{
if (hid_init())//实际上不调用它hid_enumerate和下面的hid_open也会自动调用
return -1;
hid_device_info* Hids, *HidsCopy;//一个用于接收设备信息的单链表,另一个用来遍历,该结构体使用unicode编码,所以下面都要用unicode处理方式
Hids = hid_enumerate(vid, pid);//获取vid为0x154F,pid为0x4304的HID设备链表,这里如果都是0就是获取所有的HID设备
HidsCopy = Hids;
LPCWSTR wpSerialNumber = L"\0";//用来去重,一个hid设备一般有多个端点,因此会读到多个
while (HidsCopy)
{
if (CompareStringW(LOCALE_INVARIANT, NORM_LINGUISTIC_CASING, wpSerialNumber, -1, HidsCopy->serial_number, -1) != CSTR_EQUAL)//去重
{
xPrintf((LPCTSTR)HidsCopy->serial_number);
wpSerialNumber = HidsCopy->serial_number;//我这里只需要序列号,实际上这个结构体还有很多数据,可以参考官方的实例
}
HidsCopy = HidsCopy->next;
}
hid_free_enumeration(Hids);//释放设备链表
return 0;
}
/*********************************************************
函数名称: OpenUSB(LPCTSTR PscSerialNumber)
函数功能: 打开USB-HID设备
输入参数:
参数1: LPCTSTR PscSerialNumber - HID设备的序列号
返回值:
成功 - 0
失败 - -1
********************************************************/
int ComBase::OpenUSB(unsigned short vid, unsigned short pid)
{
if (MsGlobal::m_VirtualVer == VER_VIRTUAL) {
return 0;
}
if (handle)
CloseUSB();
handle = hid_open(vid, pid, NULL);//打开指定vid、pid、序列号的设备
if (!handle)
{
xPrintf("无法打开USB设备");
hid_exit();
return -1;
}
// 将hid_read()函数设置为非阻塞。
if (hid_set_nonblocking(handle, 1) != 0)// 1启用非阻塞 0禁用非阻塞。
{
xPrintf("设置非阻塞失败");
hid_close(handle);
hid_exit();
return -2;
}
return 0;
}
//关闭USB-HID设备
/*********************************************************
函数名称: CloseUSB(hid_device*& handle)
函数功能: 关闭USB-HID设备
输入参数:
参数1: hid_device*& handle - 操作句柄
********************************************************/
void ComBase::CloseUSB()
{
if (MsGlobal::m_VirtualVer == VER_VIRTUAL) {
return;
}
if (handle)
{
hid_close(handle);
hid_exit();
}
handle = nullptr;//这里将指针置空,增强安全性
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// 线程执行的函数
unsigned int WINAPI ThreadSendMsg(LPVOID lpThreadParameter)
{
ComBase *m_pDev = (ComBase *)lpThreadParameter;
if (!m_pDev) {
xPrintf("lpThreadParameter error");
return -1;
}
sBuff *pBuff = m_pDev->getBuff();
if (!pBuff || pBuff->len == 0) {
xPrintf("getBuff error");
return -2;
}
hid_device *handle = m_pDev->getHID();
if (handle == INVALID_HANDLE_VALUE) {
xPrintf("getHID error");
return -3;
}
// 读取数据并清空缓存
int leftNum = 1;
while (leftNum)
{
unsigned char buf[1024];
memset(buf, 0, 1024);
leftNum = hid_read_timeout(handle, buf, sizeof(buf), 0);
if (leftNum < 0) {
xPrintf("hid_read_timeout error");
return -4;
}
}
// 此处对消息进行加密,从第三个字节开始
GCS_Msg_Encryption(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]);
// 此处分包,目前支持64个字节(加上id一共65个字节)
int size = 64;
int packs = pBuff->len / size * size;
if (pBuff->len % size != 0)
{
packs++;
}
int result = 0;
for (int i = 0; i < packs; i++)
{
int rlen = size;
if (i * size > pBuff->len)
rlen = pBuff->len - (i - 1) * size;
UCHAR OutputReport[65];
memset(OutputReport, 0, 65);
memcpy(&OutputReport[1], &pBuff->udata[i * size], rlen);
int iResp = hid_write(handle, OutputReport, 65);
if (iResp < 0) {
xPrintf("hid_write error");
result = -5;
break;
}
}
ExitThread(result);
}
int ComBase::SendMsg(unsigned char* Send, size_t nLength)
{
/// 初始化缓存
this->m_pBuff->stop = 0;
this->m_pBuff->len = nLength;
memcpy(this->m_pBuff->udata, Send, nLength);
/// 启动发送线程
unsigned int dwThreadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadSendMsg, (void *)this, 0, &dwThreadID);
if (hThread == NULL) {
xPrintf("_beginthreadex Error!");
return -1;
}
/// 线程阻塞
DWORD wr = WaitForSingleObject(hThread, 3000);
switch (wr)
{
case WAIT_FAILED:
{
xPrintf("thread wait failed");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -2;
}
break;
case WAIT_TIMEOUT:
{
xPrintf("thread wait timeout");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -3;
}
break;
default:
break;
}
/// 获取线程函数的返回值
DWORD dwExitCode;
GetExitCodeThread(hThread, &dwExitCode);
if (dwExitCode != 0)
{
xPrintf("thread exit code error");
CloseHandle(hThread);
return -4;
}
CloseHandle(hThread);
return 0;
}
// 线程执行的函数
unsigned int WINAPI ThreadReceiveMsg(LPVOID lpThreadParameter)
{
ComBase *m_pDev = (ComBase *)lpThreadParameter;
if (!m_pDev) {
xPrintf("lpThreadParameter error");
return -1;
}
sBuff *pBuff = m_pDev->getBuff();
if (!pBuff || pBuff->len != 0) {
xPrintf("getBuff error");
return -2;
}
hid_device *handle = m_pDev->getHID();
if (handle == INVALID_HANDLE_VALUE) {
xPrintf("getHID error");
return -3;
}
int result = 0;
while (!pBuff->stop)
{
UCHAR recvDataBuf[1024];
memset(recvDataBuf, 0, 1024);
int len = hid_read(handle, recvDataBuf, 65);
if (len > 0)
{
memcpy(&pBuff->udata[pBuff->len], recvDataBuf, len);
pBuff->len += len;
if (pBuff->udata[0] != 0xE5)
{/// 无效数据
xPrintf("read data exception\n");
result = -4;
break;
}
else
{/// 有效数据
int msglen = pBuff->udata[1] + 2;
if (msglen <= pBuff->len)
{/// 接收完成
// 此处对消息进行解密,从第三个字节开始
GCS_Msg_Decrypt(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]);
//计算crc16
uint16_t crc = crc16_modbus(&pBuff->udata[0], msglen - 2);
uint8_t crc_low = crc & 0xFF;
uint8_t crc_high = (crc >> 8) & 0xFF;
if (crc_low != pBuff->udata[msglen - 1] ||
crc_high != pBuff->udata[msglen - 2])
{
xPrintf("crc error\n");
result = -5;
break;
}
else
{
xPrintf("read data finish\n");
result = 0;
break;
}
}
else
{/// 接收未完成
xPrintf("read data unfinish\n");
continue;
}
}
}
}
ExitThread(result);
}
int ComBase::ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength)
{
/// 刷新缓存
this->m_pBuff->stop = 0;
this->m_pBuff->len = 0;
memset(this->m_pBuff->udata, 0, 10240);
/// 启动接收线程
unsigned int dwThreadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadReceiveMsg, (void *)this, 0, &dwThreadID);
if (hThread == NULL) {
xPrintf("_beginthreadex error!");
return -1;
}
/// 线程阻塞
DWORD wr = WaitForSingleObject(hThread, 3000);
switch (wr)
{
case WAIT_FAILED:
{
xPrintf("thread wait failed");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -2;
}
break;
case WAIT_TIMEOUT:
{
xPrintf("thread wait timeout");
this->m_pBuff->stop = 1;
CloseHandle(hThread);
return -3;
}
break;
default:
break;
}
/// 获取线程函数的返回值
DWORD dwExitCode;
GetExitCodeThread(hThread, &dwExitCode);
if (dwExitCode != 0)
{
xPrintf("thread exit code error");
CloseHandle(hThread);
return -4;
}
/// 根据协议拷贝有效的消息部分
nLength = this->m_pBuff->udata[1] + 2;
memcpy(pReceiveBuf, this->m_pBuff->udata, nLength);
CloseHandle(hThread);
return 0;
}
这段代码实现了什么功能,让我读懂每一行代码
最新发布