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

来源:互联网 发布:网络小笼包什么意思 编辑:程序博客网 时间:2024/05/13 13:24
源代码如下:(生成.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
原创粉丝点击