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

文章链接: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设备

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
赋所有源代码,开发工具vs2010 framework3.5 baidu搜索c# HidUsb都是大同小异案例,而且拿下来基本不能用。大都是围绕public static extern int CreateFile(省略众多参数..);发现没有,copy下来测试基本都是用不了的。 原因很简单:windows不允许你用程序随便就去访问硬件设备。所以在此把之前做过的基于C#开发HidUsb设备的项目整理成一个简单的小案例,分享给大家,开发环境VS2010。 该案例重点在public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); 看着貌似也是用到CreateFile这个函数,其实并不然,注意到没有"SafeFileHandle",这就是重点! 这样windows是允许程序访问外接hidusb设备的。 当然具体如何运用这个函数现在已经不是您应该 关心的了,因为我已经为您把它封装成一个,您只要调用相应的方法就OK. 例: //第一步:获取HidUsb设备信息 List slist = new List(); UsbHidDevice usbhid = new UsbHidDevice(); usbhid.GetDeviceList(ref slist); //HidUsb设备信息包含在List数据集中 注:当获取HidUsb设备信息为:\\?\hid#vid_0e2c&pid;_0112#6&1b44c403;&0&0000;#{4d1e55b2-f16f-11cf-88cb-001111000030}, 注意该字符串里的“vid_0e2c”和“pid_0112”部分,那么: vid为0e2c, pid为:0112 //第二步:创建一个HidUsb设备访问实例 UsbHidDevice Device = new UsbHidDevice(vid, pid); //第三步:连接HidUsb设备 Boolean connBool = Device.Connect(); //第四步:实现数据接收事件 Device.DataReceived += new UsbHidDevice.DataReceivedDelegate(Device_DataReceived); //当HidUsb设备返回信息时触发此事件 void Device_DataReceived(byte[] data) { //处理接收到的数据逻辑 } //第五步:向Hid设备发送数据"0xa0 00 0x12 0x9 0x22" string txt = "0xa0 00 0x12 0x9 0x22"; //把数据转换为字节数组 byte[] data = ConvertHelper.StringToByte(txt2); byte bt = 0; CommandMessage cmdMsg = new CommandMessage(bt, data); Boolean sbool = Device.SendMessage(cmdMsg); //发送数据 //第六步:释放所有资源 Device.Dispose();
baidu搜索c# HidUsb都是大同小异案例,而且拿下来基本不能用。大都是围绕public static extern int CreateFile(省略众多参数..);发现没有,copy下来测试基本都是用不了的。 原因很简单:windows不允许你用程序随便就去访问硬件设备。所以在此把之前做过的基于C#开发HidUsb设备的项目整理成一个简单的小案例,分享给大家,开发环境VS2010。 该案例重点在public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); 看着貌似也是用到CreateFile这个函数,其实并不然,注意到没有"SafeFileHandle",这就是重点! 这样windows是允许程序访问外接hidusb设备的。 当然具体如何运用这个函数现在已经不是您应该关心的了,因为我已经为您把它封装成一个,您只要调用相应的方法就OK. 例: 获取HidUsb设备信息 List slist = new List(); UsbHidDevice usbhid = new UsbHidDevice(); usbhid.GetDeviceList(ref slist); //HidUsb设备信息包含在List数据集中 当获取HidUsb设备信息为:\\?\hid#vid_0e2c&pid_0112#6&1b44c403&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} 那么: vid为0e2c, pid为:0112 //创建一个HidUsb设备访问实例 UsbHidDevice Device = new UsbHidDevice(vid, pid); //实现数据接收事件 Device.DataReceived += new UsbHidDevice.DataReceivedDelegate(Device_DataReceived); //当HidUsb设备返回信息时触发此事件 void Device_DataReceived(byte[] data){ } //向Hid设备发送数据"0xa0 00 0x12 0x9 0x22" string txt = "0xa0 00 0x12 0x9 0x22"; //把数据转换为字节数组 byte[] data = ConvertHelper.StringToByte(txt2); byte bt = 0; CommandMessage cmdMsg = new CommandMessage(bt, data); Boolean sbool = Device.SendMessage(cmdMsg); //发送数据 Device.Dispose(); //释放所有资源

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值