USB HID类设备开发中用CreateFile无法得到设备句柄

Mouse和Keyboard这类HID类设备是被系统独占的,若想用CreateFile得到句柄需把第二个参数为0;

 

CString strShow;

 int flag=0;
 int vid = 0x046D;
 int pid = 0xC040;

 //获得GUID
 GUID guidHID;
 HidD_GetHidGuid(&guidHID);

 strShow=_T("HID类的GUID标识为:/r/n");
 ShowMessage(strShow);
 strShow.Format(_T("  %08x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x/r/n"),
  guidHID.Data1,guidHID.Data2,guidHID.Data3,guidHID.Data4[0],
  guidHID.Data4[1],guidHID.Data4[2],guidHID.Data4[3],guidHID.Data4[4],
  guidHID.Data4[5],guidHID.Data4[6],guidHID.Data4[7]);
 ShowMessage(strShow);

 //获得HID的结构数组调用函数SetupDiGetClassDevs,获得HID的结构数组
 HDEVINFO hDevInfo = SetupDiGetClassDevs(
  &guidHID,
  NULL,
  0,
  DIGCF_PRESENT|DIGCF_DEVICEINTERFACE );


 //根据此数组逐项查找指定的HID
 SP_DEVICE_INTERFACE_DATA strtInterfaceData;
 strtInterfaceData.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
 BOOL usbSuccess,pathSuccess;
 DWORD index=0;
 CString temp;
 for(int i=0;flag==0 && i<10;i++)//一个USB接口理论上可以支持127个装置,但是目前还无法达到这个数字。其实,对于一台计算机,所接的周边外设很少有超过10个的,因此这个数字是足够我们使用的。
 {
  strShow.Format(_T("/r/n第%d次查找开始:/r/n"),i);
  ShowMessage(strShow);
  //识别HID接口调用函数SetupDiEnumDeviceInterfaces,识别当前HID接口
  usbSuccess= SetupDiEnumDeviceInterfaces(
   hDevInfo,//SetupDiGetClassDevs的返回值
   NULL,
   &guidHID,//通过HidD_GetHidGuid函数获得的GUID
   index,//第一次调用设置为0
   &strtInterfaceData);


  index++;
  if(usbSuccess)//识别当前HID接口成功
  { 
   ShowMessage(_T("当前HID接口信息:/r/n"));
   strShow.Format(_T("  cbsize:%d/r/n"),strtInterfaceData.cbSize);
   ShowMessage(strShow);
   strShow.Format(_T("  Flags:%d/r/n"),strtInterfaceData.Flags);
   ShowMessage(strShow);

 

   // 若找到了设备,则读取设备路径名
   ULONG         predictedLength   =   0;  
   ULONG         requiredLength   =   0; 
   BOOL pathSuccess;
   SP_DEVICE_INTERFACE_DETAIL_DATA * strtDetailData;
   ShowMessage(_T("连续两次调用函数SetupDiGetDeviceInterfaceDetail,获得当前HID设备路径.../r/n"));

   pathSuccess=SetupDiGetDeviceInterfaceDetail(hDevInfo,&strtInterfaceData,NULL,0,&requiredLength,NULL);//第一次调用返回pathSuccess=0

   ShowMessage(_T("  第一次调用成功.../r/n")); 
   strShow.Format(_T("  获得需要数据区域大小为:%d/r/n"),requiredLength);

   predictedLength=requiredLength;


   strtDetailData= (PSP_INTERFACE_DEVICE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, predictedLength);
   ShowMessage(_T("  按需要重新分配内存成功/r/n")); 
   strtDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
   strShow.Format(_T("  获取cbSize:%d/r/n"),strtDetailData->cbSize);

   pathSuccess=SetupDiGetDeviceInterfaceDetail(hDevInfo,&strtInterfaceData,strtDetailData,predictedLength,&requiredLength,NULL);
   ShowMessage(_T("  第二次调用成功.../r/n"));

   m_strPath = strtDetailData->DevicePath;
   strShow.Format(_T("  返回路径DevicePath:%s/r/n"),m_strPath);
   m_strLog += strShow;
   SetDlgItemText(IDC_EDIT_REPORT,m_strLog);


   //获得设备句柄
   hCom = CreateFile(m_strPath,0,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,        // no SECURITY_ATTRIBUTES structure
    OPEN_EXISTING, // No special create flags
    0,
    NULL);
   if(hCom == INVALID_HANDLE_VALUE)
   {
    ShowMessage(_T("调用函数CreateFile,获得句柄失败!/r/n"));
   }
   else
   {
    ShowMessage(_T("调用函数CreateFile,获得句柄成功!/r/n"));
   }
   
   strShow.Format(_T("  返回句柄:%p/r/n"),&hCom);
   ShowMessage(strShow);


   //获得设备的厂商ID、产品ID和产品序列号
   ShowMessage(_T("调用函数HidD_GetAttributes,获取设备的厂商ID、产品ID和产品序列号.../r/n"));
   HIDD_ATTRIBUTES strtAttrib;
   BOOL Result;
   Result=HidD_GetAttributes(hCom,&strtAttrib);
   if(Result) 
   {
    strShow.Format(_T("  返回厂商ID值(十进制):%X/r/n  返回产品ID值(十进制):%X/r/n  返回产品序列号值(十进制):%X/r/n"),
     strtAttrib.VendorID,strtAttrib.ProductID,strtAttrib.VersionNumber);
   }
   else
   {
    strShow = _T("HidD_GetAttributes Error!/r/n");
   }
   ShowMessage(strShow);

 

 

   // 将查到的匹配的设备的标识显示出来
   if(strtAttrib.VendorID== vid &&strtAttrib.ProductID==pid)
   {
    strShow.Format(_T("找到符合条件的HID设备,停止查找。/r/n"),i);
    ShowMessage(strShow);
    ShowMessage(_T("显示设备信息如下:/r/n"));

    //显示厂商标识
    strShow.Format(_T("  厂商标识:0x%x/r/n"),strtAttrib.VendorID);
    m_strLog += strShow;
    SetDlgItemText(IDC_EDIT_REPORT,m_strLog);

    //显示产品标识
    strShow.Format(_T("  产品标识:0x%x/r/n"),strtAttrib.ProductID);
    m_strLog += strShow;
    SetDlgItemText(IDC_EDIT_REPORT,m_strLog);

    //显示产品版本号
    strShow.Format(_T("  产品序列号:%d/r/n"),strtAttrib.VersionNumber);
    m_strLog += strShow;
    SetDlgItemText(IDC_EDIT_REPORT,m_strLog);

    ShowMessage(_T("此时可以在通信区进行收发报表操作!/r/n"));

    AfxMessageBox(_T("FIND HID!"));
    //找到则跳出循环
    flag=1;
   }
   else
   {
    strShow.Format(_T("匹配设备的厂商标识和产品标识不成功,结束此次查找!/r/n"),i);
    ShowMessage(strShow);
   }
  }
  else//识别当前HID接口操作不成功
  {
   ShowMessage(_T("识别当前HID接口操作不成功,结束此次查找!/r/n"));
  }
 }//for循环结束

 if(flag==0)//10次查找完成,找不到符合条件的HID设备
 {
  ShowMessage(_T("已完成N次查找,找不到符合条件的HID设备!/r/n"));
 }

 

参照USBPort源码修改,功能查找某个PID,VID的HID设备

你可能感兴趣的:(USB)