您的位置:首页 > 编程语言 > C语言/C++

C++ 实现USB - HID读写数据

2017-06-30 15:07 330 查看
源代码--如下:

1.MCDInterface.h
/*
*MCDInterface.h
*author:
*data:
*/

#ifndef MCDBOX_H_INCLUDED
#define MCDBOX_H_INCLUDED
#pragma once
#define MCD_IOCTRL_OPEN_SIG 0x1001
#define MCD_IOCTRL_CLOSE_SIG 0x1002
#define MCD_IOCTRL_FIND_SIG 0x1003
#define MCD_IOCTRL_READY 0x1003
#define MCD_IOCTRL_UNREADY 0x1004
#define KEY_0 0x3A
#define KEY_1 0x3B
#define KEY_2 0x3C
#define KEY_3 0x3D
#define KEY_4 0x3E
#define KEY_5 0x3F
#define KEY_6 0x40
#define KEY_7 0x41
#define KEY_8 0x42
#define KEY_9 0x43
#define KEY_STAR 0x44
#define KEY_POUND 0x45
#define MSG_HOOKOFF 0x16
#define MSG_HOOKON 0x12
#define MSG_RINGING 0x15
#define HID_DEVICE_REMOVE 0x76 //硬件被移走
#define CLIENT_READY_WRITE_SIG 0x92 //通知设备软件正在运行,每隔一段时间向缓冲区写该数据
#define DLL_EXPORT __declspec(dllexport)
#define DLL_IMPORT __declspec(dllimport)
//定义用于回调的枚举消息
enum{
MCD_CALLBACK_MSG_VERSION,//not used
MCD_CALLBACK_MSG_SERIALNO,//not used
MCD_CALLBACK_DEVICE_FOUND,
MCD_CALLBACK_DEVICE_NOT_FOUND,
MCD_CALLBACK_DEVICE_REMOVE,

MCD_CALLBACK_KEYDOWN,
MCD_CALLBACK_KEYBUFFER_CHANGED,
MCD_CALLBACK_HOOKOFF,
MCD_CALLBACK_HOOKON,
MCD_CALLBACK_RINGING,
MCD_CALLBACK_MSG_WARNING = -2,
MCD_CALLBACK_MSG_ERROR = -1,
};
DLL_EXPORT unsigned long MCD_DeviceIoControl(unsigned long dwIoControlCode,
void* lpInBuffer = 0, unsigned long nInBufferSize = 0,
void* lpOutBuffer = 0, unsigned long nOutBufferSize = 0);
//定义设备状态返回信息
enum{
MCD_RETURN_SUCCESS = 0,
MCD_RETURN_FOUND_HID,
MCD_RETURN_NO_FOUND_HID,
MCD_RETURN_HID_IS_OPENED,//?
MCD_RETURN_HID_NO_OPEN,//?
};
#endif // MCDBOX_H_INCLUDED
2.mcdHid.h
#ifndef MCDHID_H_INCLUDED
#define MCDHID_H_INCLUDED
extern "C"
{
#include "setupapi.h"
#include "hidsdi.h"
#include "dbt.h"
}
typedef struct _HID_DEVICE {
PCHAR DevicePath;
HANDLE HidDevice; // A file handle to the hid device.
HIDP_CAPS Caps; // The Capabilities of this hid device.
HIDD_ATTRIBUTES Attributes;
} HID_DEVICE, *PHID_DEVICE;

class MCDHid
{
public:
static MCDHid & getInstance(){
static MCDHid mcdHid;
return mcdHid;
}
MCDHid(MCDHid & mcdHid);
MCDHid & operator=(MCDHid &mcdHid);
~MCDHid();
unsigned long openMCDHid();
void closeMCDHid();
void startComm(void * pParam);

int writeToHid();

int readFromHid();
char * getHidDeviceName()
{
return _hidDeviceName;
}
bool findMCDHid();
HID_DEVICE* getHidDevice(){
return & _hidDevice;
}
bool getUsbCommRunning(){
return _fUsbCommRunning;
}
bool getOffHookSignal(){
return _offHookSignal;
}
unsigned long getDataWaitProcess(){
return _dataWaitProcess;
}
void setUsbCommRunning(bool usbCommRunning)
{
_fUsbCommRunning = usbCommRunning;
}
unsigned char _inputReportBuffer[9];
unsigned char _outputReportBuffer[2];

private:
MCDHid();
void copy(MCDHid & mcdHid);
char *_hidDeviceName;
HANDLE _hEventObject;
OVERLAPPED _hIDOverlapped;
HID_DEVICE _hidDevice;

bool _fUsbCommRunning;
bool _offHookSignal;
unsigned long _dataWaitProcess;
unsigned long _inputReportByteLength;
unsigned long _outputReportByteLength;
};

#endif // MCDHID_H_INCLUDED

3.mcdHid.cpp
/*
mcdhid.cpp
function: open HID device ,close HID device ,read data from HID device , write data to HID device
author:
date:
version:
*/
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include "mcdhid.h"
#include "MCDInterface.h"
#include "mcdbox.h"
#include "pthread.h"

void *getDataThread(void *pParam);
#define VENDOR_ID 0x1241//test device vendorId
#define PRODUCT_ID 0xe001//test device productId
#define CLIENT_RUNNING_MSG

MCDHid::MCDHid()
{
_hidDeviceName = "MCD Human Interface Device";

_fUsbCommRunning = false;
_offHookSignal = false;
_dataWaitProcess = 1;
memset(_inputReportBuffer,0,sizeof(_inputReportBuffer));
memset(_outputReportBuffer,0,sizeof(_outputReportBuffer));
}
MCDHid::MCDHid(MCDHid & mcdHid)
{
copy(mcdHid);
}
MCDHid & MCDHid::operator=(MCDHid & mcdHid)
{
copy(mcdHid);
return *this;
}
void MCDHid::copy(MCDHid & mcdHid)
{
_hidDeviceName = mcdHid._hidDeviceName;
_hEventObject = mcdHid._hEventObject;
_hIDOverlapped = mcdHid._hIDOverlapped;
_hidDevice = mcdHid._hidDevice;
_fUsbCommRunning = mcdHid._fUsbCommRunning;
_offHookSignal = mcdHid._offHookSignal;
_dataWaitProcess = mcdHid._dataWaitProcess;
_inputReportByteLeng
4000
th = mcdHid._inputReportByteLength;
_outputReportByteLength = mcdHid._outputReportByteLength;
for(int i = 0; i<sizeof(_inputReportBuffer); i++)
{
_inputReportBuffer[i] = mcdHid._inputReportBuffer[i];
}
for(int i = 0; i<sizeof(_outputReportBuffer); i++)
{
_inputReportBuffer[i] = mcdHid._outputReportBuffer[i];
}
}
MCDHid::~MCDHid()
{
}
unsigned long MCDHid::openMCDHid()
{
if(findMCDHid())
{
//采用重叠传输方式
//if( _hEventObject == 0)
// {

_hEventObject = CreateEvent(
NULL,
true,
true,
"");
_hIDOverlapped.hEvent = _hEventObject;
_hIDOverlapped.Offset = 0;
_hIDOverlapped.OffsetHigh =0;
// }

return MCD_RETURN_SUCCESS;
}
else
return MCD_RETURN_NO_FOUND_HID;
}
void MCDHid::closeMCDHid()
{
CloseHandle(_hidDevice.HidDevice);
_hidDevice.HidDevice = INVALID_HANDLE_VALUE;
}
void MCDHid::startComm(void *pParam)
{
int thr_id;
pthread_t m_processT;

if((thr_id=pthread_create(&m_processT, NULL, getDataThread, pParam) != 0))
{
//printf("pthread_create error:%s\n", strerror(thr_id));
return;
}
}
bool MCDHid::findMCDHid()
{
int vendorID = VENDOR_ID;
int productID = PRODUCT_ID;
DWORD required;
GUID hidGuid;
HDEVINFO hDevInfo;
SP_DEVICE_INTERFACE_DATA devInfoData;
int memberIndex = 0;
LONG result;
bool lastDevice = false;
DWORD length;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
bool deviceDetected = false;

HidD_GetHidGuid(&hidGuid);
hDevInfo = SetupDiGetClassDevs
(&hidGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
//当应用程序不再需要使用SetupDiGetClassDevs函数的传回值hDevInfo所指的数组时,应该调用SetupDiDeStroyDeviceInfoList函数来释放资源
if(hDevInfo == INVALID_HANDLE_VALUE)
{
//printf("Failed to open device handle!");
return false;
}

devInfoData.cbSize = sizeof(devInfoData);
do
{
result = SetupDiEnumDeviceInterfaces(
hDevInfo,
0,
&hidGuid,
memberIndex,
&devInfoData);
if (result != 0)
{
result = SetupDiGetDeviceInterfaceDetail(
hDevInfo,
&devInfoData,
NULL,
0,
&length,
NULL);
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(length);
if(!detailData)
{
//printf("Device information allacation failed!");
return false;
}
detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
result = SetupDiGetDeviceInterfaceDetail(
hDevInfo,
&devInfoData,
detailData,
length,
&required,
NULL);
if(!result)
{
//printf("Device information reallocation failed!");
return false;
}
_hidDevice.HidDevice = CreateFile(
detailData->DevicePath,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);

_hidDevice.Attributes.Size = sizeof(HIDD_ATTRIBUTES);
result = HidD_GetAttributes(
_hidDevice.HidDevice,
&_hidDevice.Attributes);
if ((_hidDevice.Attributes.VendorID == vendorID) && (_hidDevice.Attributes.ProductID == productID))
{
int status;
PHIDP_PREPARSED_DATA PreparsedData ;
deviceDetected = true;

//获取USB设备的预解析数据
result = HidD_GetPreparsedData(_hidDevice.HidDevice,&PreparsedData);
if(!result)
{
//printf("无法获取USB设备的预解析数据!");
return false;
}
status= HidP_GetCaps(PreparsedData, &_hidDevice.Caps);
_fUsbCommRunning = true;
HidD_FreePreparsedData(PreparsedData);
PreparsedData = NULL;

}
else
{
//printf("没有找到设备!");
closeMCDHid();
}
free(detailData);
detailData = NULL;
}
else
{
lastDevice = true;
}
memberIndex = memberIndex + 1;
}while((lastDevice == false)&&(deviceDetected == false));

SetupDiDestroyDeviceInfoList(hDevInfo);
return deviceDetected;
}
/*
*写入数据为MCD设备状态通知,把标识位放在第1位
*/
int MCDHid::writeToHid()
{
return 0;
}
int MCDHid::readFromHid()
//int readFromHid()
{
if(_hidDevice.HidDevice != INVALID_HANDLE_VALUE)
{
int result = 0;
DWORD numberOfBytesRead;

result = ReadFile(_hidDevice.HidDevice,
&_inputReportBuffer,
_hidDevice.Caps.InputReportByteLength,
&numberOfBytesRead,
(LPOVERLAPPED)&_hIDOverlapped);
_inputReportByteLength = _hidDevice.Caps.InputReportByteLength;
}
int waitResult = 0;
waitResult = WaitForSingleObject(
_hEventObject,
10);
switch(waitResult)
{
case WAIT_OBJECT_0: break;
case WAIT_TIMEOUT:
{
CancelIo(_hidDevice.HidDevice);
break;
}
default:
{
break;
}
}
ResetEvent(_hEventObject);
return 0;
}
/**************************************************************************
*启动一个读取数据线程,读取数据为拨打电话号码
*启动一个写入数据线程, 写入数据为MCD设备状态通知,现在还没有写数据
***************************************************************************/

void *getDataThread(void *pParam)
{
MCDBox *ht = (MCDBox *)pParam;
MCDHid *hr = &(MCDHid::getInstance());

while(hr->getUsbCommRunning())//USB设备running,并且有摘机信号
{
hr->readFromHid();
//readFromHid();
//printf("获取缓冲区的数据\n");

if(hr->getDataWaitProcess() > 0)//可以定义_dataWaitProcess为一次拨号数据的长度
{
unsigned long i = 0;

for(i = 0; i < 9; i++)
{
ht->_inputReportBuffer[i] = hr->_inputReportBuffer[i];
//printf("read data from device is:%d\n",ht->_inputReportBuffer[1]);
}
ht->processData();
memset(hr->_inputReportBuffer,0,sizeof(hr->_inputReportBuffer));
//printf("数据处理!\n");
}
int status = 0;
//PHIDP_PREPARSED_DATA PreparsedData ;
//status = HidD_GetPreparsedData(_hidDevice.HidDevice,&PreparsedData);
status = HidD_GetAttributes(
hr->getHidDevice()->HidDevice,
&hr->getHidDevice()->Attributes);
if(!status)
{
hr->setUsbCommRunning(false);
memset(ht->_inputReportBuffer,0,sizeof(ht->_inputReportBuffer));
ht->_inputReportBuffer[2] = HID_DEVICE_REMOVE;
ht->processData();
printf("设备移走!");
//return false;
break;
}
//HidD_FreePreparsedData (PreparsedData);
// PreparsedData = NULL;
Sleep(100);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: