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

源代码--如下:

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
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值