您的位置:首页 > 其它

USB HID类设备开发中用CreateFile无法得到设备句柄,读访问失败

2017-12-08 08:52 281 查看
文章链接:http://blog.csdn.net/seth1104/article/details/4489306

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设备
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐