USB HID设备读写代码实现c++

  • Post author:
  • Post category:其他


源代码如下:(生成.dll .lib)

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;
_inputReportByteLength = 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;

}

4.mcdbox.h
#ifndef MCDMAIN_H_INCLUDED

#define MCDMAIN_H_INCLUDED
class MCDHid;

class MCDCallBack;
class MCDBox

{

public:
static MCDBox & getInstance(){

static MCDBox mcdBox;

return mcdBox;

}
~MCDBox();
unsigned long deviceIOControl(unsigned long dwIoControlCode,

void* lpInBuffer,  unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize);
void findDevice(void* lpInBuffer, unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize);
unsigned long openDevice(void* lpInBuffer, unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize);
void closeDevice();
void processData();
unsigned char _inputReportBuffer[9];
unsigned char _outputReportBuffer[9];
unsigned long _inputBufferByteLength;
unsigned long _outputBufferByteLength;
bool isDeviceOpen(){

return _openDevice;

}
void setDeviceOpen(bool deviceOpen)

{

_openDevice = deviceOpen;

}

private:
MCDBox();
char * _mcdHidName;
unsigned long _mcdStatus;
MCDHid & _mcdHid;
MCDCallBack &_mcdCallback;
bool _openDevice;
//char _key;
};
/*

*定义回调函数

*/

typedef void (*CALLBACK_MCDBOX)(void* wParam, void* lParam, unsigned long ParameterOfApp);

class MCDCallBack

{
public:
static MCDCallBack & getInstance(){

static MCDCallBack mcdCallback;

return mcdCallback;

}
MCDCallBack(MCDCallBack & mcdCallback);
MCDCallBack & operator=(MCDCallBack & mcdCallback);
virtual ~MCDCallBack();
void create(void* pCallBackFunction = 0, unsigned long dwParameterOfApplication = 0);
void callBack(unsigned long wParam,void* lParam = 0);
private:
MCDCallBack();
void copy(MCDCallBack  & mcdCallback);
struct {

CALLBACK_MCDBOX func;

unsigned long lParam;

}_fCallBack;

};
//extern MCDCallBack mcdCallBack;
#endif // MCDMAIN_H_INCLUDED
5.cpp
/*

mcdbox.cpp

function description: 数据处理接口

author:

date:

version:

*/

#ifndef MCDBOX_CPP_INCLUDED

#define MCDBOX_CPP_INCLUDED

#include <windows.h>

#include <stdio.h>
#include “mcdbox.h”

#include “MCDInterface.h”

#include “mcdhid.h”

#include “pthread.h”

void *findDeviceThread(void *param);

unsigned long MCD_DeviceIoControl(unsigned long dwIoControlCode,

void* lpInBuffer,  unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize)

{

unsigned long br = 0;

MCDBox *ht = (MCDBox *)&(MCDBox::getInstance());

//MCDBox  ht = getInstance();;

try

{

br = ht->deviceIOControl(dwIoControlCode,lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);

}

catch (unsigned long BytesReturned)

{

br = BytesReturned;

}

return br;

}
MCDBox::MCDBox()

:_mcdHid(MCDHid::getInstance()),

_mcdCallback(MCDCallBack::getInstance())

{

_openDevice =false;

_inputBufferByteLength = 8;

_outputBufferByteLength = 8;
for (int i = 0; i < (int)_inputBufferByteLength; i++)

{

_inputReportBuffer[i] = 0;

}

for (int j = 0;j < (int)_outputBufferByteLength; j++)

{

_outputReportBuffer[j] = 0;

}

}
MCDBox::~MCDBox()

{

}
unsigned long MCDBox::deviceIOControl(unsigned long dwIoControlCode,

void* lpInBuffer,  unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize)

{

switch (dwIoControlCode)

{

case MCD_IOCTRL_FIND_SIG:

findDevice(lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);

break;

case MCD_IOCTRL_CLOSE_SIG:

if (_openDevice)

{

closeDevice();

}

_mcdHid.closeMCDHid();

_openDevice = false;

return 0;
case MCD_IOCTRL_OPEN_SIG:

if (_openDevice)

return MCD_RETURN_HID_IS_OPENED;

openDevice(lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);

break;
//case CLIENT_READY_WRITE_SIG://软件运行正常,通知硬件设备

//    _mcdHid.writeToHid();

//    return 0;
default:

if (!_openDevice) return MCD_RETURN_HID_NO_OPEN;

break;

}

return 0;

}
void MCDBox::findDevice(void* lpInBuffer, unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize)

{

pthread_t m_processT;

int threadID;

_mcdCallback.create(lpInBuffer,nInBufferSize);

if((threadID=pthread_create(&m_processT, NULL, findDeviceThread, this) != 0))

{

return ;

}

}

unsigned long MCDBox::openDevice(void* lpInBuffer, unsigned long nInBufferSize,

void* lpOutBuffer, unsigned long nOutBufferSize)

{

_mcdCallback.create(lpInBuffer,nInBufferSize);

unsigned long dwReturnValue = _mcdHid.openMCDHid();

if(dwReturnValue == MCD_RETURN_SUCCESS)

{

_openDevice = true;

// _mcdCallback.create(lpInBuffer,nInBufferSize);

_mcdStatus = MCD_IOCTRL_READY;

//_mcdHid.writeToHid();//软件运行正常,通知硬件设备

//_key = 0;

_mcdHid.startComm(this);

_mcdHidName = _mcdHid.getHidDeviceName();

}

else

{

_mcdHid.closeMCDHid();

}

return dwReturnValue;

}

void MCDBox::closeDevice()

{

_mcdHid.closeMCDHid();

}
/********************************************************************************

/***读取缓冲区,第二个字节为有效数据,buffer size = 8bytes。。。(目前暂定)

*********************************************************************************/

void MCDBox::processData()

{

/*

*test:对key_buffer赋值为0x34,看能否回调成功,test结果:right!

*/

unsigned long isExist = _inputReportBuffer[2];

if(isExist == HID_DEVICE_REMOVE)

{

//printf(“device removed/n”);

_openDevice = false;

_mcdCallback.callBack(MCD_CALLBACK_DEVICE_REMOVE,(void*)0);

closeDevice();

return;

}
unsigned char key_buffer = _inputReportBuffer[1];

if(key_buffer > 0x00 && key_buffer < 0x3A)

{

if(key_buffer == MSG_HOOKOFF)

{

_mcdCallback.callBack(MCD_CALLBACK_HOOKOFF,(void*)key_buffer);

key_buffer = 0x00;

//printf(“MSG_HOOKOFF/n”);

return;

}

if(key_buffer == MSG_HOOKON)

{

_mcdCallback.callBack(MCD_CALLBACK_HOOKON,(void*)key_buffer);

key_buffer = 0x00;

//printf(“MSG_HOOKON/n”);

return;

}

if(key_buffer == MSG_RINGING)

{

_mcdCallback.callBack(MCD_CALLBACK_RINGING,(void*)key_buffer);

key_buffer = 0x00;

//printf(“MSG_RINGING/n”);

return;

}

}

else if(key_buffer >= KEY_0 && key_buffer <= KEY_POUND)//should be ||,or not be &&??

{

_mcdCallback.callBack(MCD_CALLBACK_KEYDOWN,(void*)key_buffer);

//printf(“您按下的是%d键/n”,(key_buffer-0X3A));

key_buffer = 0x00;

return;

}

else

{

return;

}

}

MCDCallBack::MCDCallBack()

{

_fCallBack.func =0;

_fCallBack.lParam = 0;

}
MCDCallBack::MCDCallBack(MCDCallBack & mcdCallback)

{

copy(mcdCallback);

}
MCDCallBack & MCDCallBack::operator=(MCDCallBack & mcdCallback)

{

copy(mcdCallback);

return *this;

}
MCDCallBack::~MCDCallBack()

{

}
void MCDCallBack::copy(MCDCallBack & mcdCallback)

{

_fCallBack.func = mcdCallback._fCallBack.func;

_fCallBack.lParam = mcdCallback._fCallBack.lParam;
}
void MCDCallBack::create(void* pCallBackFunction, unsigned long dwParameterOfApplication )

{

_fCallBack.func = (CALLBACK_MCDBOX)pCallBackFunction;

_fCallBack.lParam = dwParameterOfApplication;

}
void MCDCallBack::callBack(unsigned long wParam,void* lParam )

{

if(_fCallBack.func)

{

(*_fCallBack.func)((void*)wParam,lParam,_fCallBack.lParam);

}

}
void *findDeviceThread(void *param)

{

bool isHidFind = false;

while(!isHidFind)

{

MCDHid &mcdHid = MCDHid::getInstance();

MCDCallBack & mcdCallback = MCDCallBack::getInstance();

isHidFind = mcdHid.findMCDHid();

if(isHidFind)

{

//printf(“find device/n”);

mcdCallback.callBack(MCD_CALLBACK_DEVICE_FOUND,(void*)0);

return 0;

}

Sleep(1000);

}

return 0;

}

#endif // MCDBOX_CPP_INCLUDED



版权声明:本文为cr4315原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。