allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
阅读:1705回复:12

没办法了,贴代码,请大虾帮忙分析一下:(

楼主#
更多 发布于:2007-09-24 17:23
之前发了几个帖子,虽然问题都没有解决,但还是要感谢那些热心回答问题的网友。
我现在的问题就是程序在相用CreateFile获得USB HID设备句柄时,总是返回无效的句柄。整个系统有3个HID设备:USB鼠标、USB键盘和一个我用开发板上的资源做的一个简易的鼠标(可以正常使用)。
在下面的程序中,通过手动修改Index的值(0,1和2)来分别定位这3个设备。

有热心的网友提示:鼠标键盘是系统独占的资源,因此无法用CreateFile获取设备句柄。
我看了USBView的源代码后,发现它也是通过CreateFile来得到设备句柄的(在enum.c文件EnumrateHub()函数中),只是它获得设备路径的方式跟我不一样,我看的不是很明白。

现在为了获得设备句柄,从而实现读写USB设备的目的,有哪几种方向可行:
1.修改我的Firmware,将设备改成非鼠标、键盘设备。(应该改成什么设备才是非系统独占的?)
2.找到系统(XP)自带的USB HID类设备驱动,修改驱动程序。(在哪里可以看到其源代码?)
3. 在应用程序中采用另外的方式读写设备。(具体这种USBView代码中的方式是什么,哪里有更多这种读写设备方式的资料?)

烦请各位大虾或有经验的网友帮忙解决一下这个问题或者提供一些思路。

下面是我按照一般读写HID设备的方式企图获取设备句柄的代码(是参照网上USBPort代码写的),看看问题在哪里?再次感谢各位!

GUID    HidGuid;
HDEVINFO    HidDevInfo;    
DWORD    Index;                            

SP_DEVICE_INTERFACE_DATA                         devInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA    devInterfaceDetailData;

DWORD        DataSize;    
DWORD        RequiredSize;
HANDLE        hDevice;

HidD_GetHidGuid(&HidGuid);
ErrorCode = GetLastError();

HidDevInfo = SetupDiGetClassDevs(  &HidGuid,
                  NULL,
                  NULL,
                  DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
ErrorCode = GetLastError();


Index = 0;                            

devInterfaceData.cbSize = sizeof(devInterfaceData);
SetupDiEnumDeviceInterfaces(    HidDevInfo,
            0,
            &HidGuid,
            Index,
            &devInterfaceData);
ErrorCode = GetLastError();

SetupDiGetDeviceInterfaceDetail(    HidDevInfo,
            &devInterfaceData,
            NULL,
            0,
            &DataSize,
            NULL);

RequiredSize = DataSize;
devInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(DataSize);
devInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

SetupDiGetDeviceInterfaceDetail(    HidDevInfo,
            &devInterfaceData,
            devInterfaceDetailData,
            DataSize,
            &RequiredSize,
            NULL);

hDevice = CreateFile(    devInterfaceDetailData->DevicePath,
        GENERIC_WRITE,
        FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

ErrorCode = GetLastError();
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-09-26 13:41
能查询就可以活动设备的VID和PID以及更多的设备信息了。
也就验证了前面的函数调用方法是正确的,可以通过那样一系列的方法找到设备。为后面继续想读写设备找到方向了,就是不要做成鼠标或键盘这类设备。反正我最终的目的是要通过上层应用程序给设备发送数据,至于是定义成什么类型的设备不重要。
oushengfen
驱动牛犊
驱动牛犊
  • 注册日期2007-06-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分747分
  • 威望124点
  • 贡献值1点
  • 好评度82点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-09-26 11:24
那你打开有什么用呢,只能查询啊,不能进行读写,如果要操作的话,是不是要写过滤驱动才行啊.
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-09-26 10:31
该参数设为0意味着:Specifies device query access to the object. An application can query device attributes without accessing the device.
不用访问设备,就可以query设备的属性。这个问题总算是明白了

而在设为GENERIC_READ或者是GENERIC_WRITE的时候,Specifies read/write access to the object. Data can be read from the file and the file pointer can be moved. Combine with GENERIC_WRITE for read-write access. 表示你要访问设备。而鼠标键盘是系统独占资源,是不允许这样的,因此会返回无效的句柄。而如果是游戏手柄之类的HID设备是不存在这个问题的,是可以获得正确的设备句柄的。
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-09-26 10:26
继续报告进展:
如果把CreateFile的第二个参数设为0的话,不管是不是鼠标键盘设备,都可以正确的得到设备的句柄!!!
也就是    
hDevice = CreateFile(    devInterfaceDetailData->DevicePath,
                            0,
                            FILE_SHARE_WRITE | FILE_SHARE_READ,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
                            NULL);
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-09-26 09:07
报告一下最新的进展:
我把我的设备拔下来
换上一个买的USB游戏手柄
就可以用上面的代码得到游戏手柄的句柄
并且然后通过HidD_GetAttributes()得到了手柄的VID和PID。

难道鼠标和键盘的句柄真的就不能通过上面的方式得到?
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-09-26 08:35
引用第6楼qiweixue于2007-09-25 20:46发表的  :
usbview
关键这三个步骤:
 (1) Enumerate Host Controllers and Root Hubs
(2) Enumerate Hubs (Root Hubs and External Hubs)
 (3) Enumerate Downstream Ports
.......


确实就是这么做的。直接进了WinMian之后就HidD_GetHidGuid(),我是参照网上流创的USBPort的程序来写了。
不能直接这么做吗?

感谢两位在中秋节的晚上还来回我的帖子,感谢!
qiweixue
驱动小牛
驱动小牛
  • 注册日期2004-07-21
  • 最后登录2011-12-19
  • 粉丝0
  • 关注0
  • 积分1006分
  • 威望274点
  • 贡献值0点
  • 好评度268点
  • 原创分1分
  • 专家分0分
7楼#
发布于:2007-09-25 20:46
usbview
关键这三个步骤:
 (1) Enumerate Host Controllers and Root Hubs
(2) Enumerate Hubs (Root Hubs and External Hubs)
 (3) Enumerate Downstream Ports

host-hub-port...

你是不是上来就去枚举HId Usb类,跳过Host或hub这一层
lejianz
驱动中牛
驱动中牛
  • 注册日期2003-03-05
  • 最后登录2023-11-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望145点
  • 贡献值0点
  • 好评度116点
  • 原创分0分
  • 专家分0分
  • 社区居民
8楼#
发布于:2007-09-25 18:43
HID GUID全球唯一, 那说明有其它的问题,你再好好查一下。另外,如果你得到设备句柄,也是不能读写的。你还是用这段代码测试其它HID类设备吧。 
一起交流,共同提高!
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2007-09-25 16:08
引用第3楼lejianz于2007-09-25 14:44发表的  :
没错,键盘和鼠标是OS独占设备,但是可以得到设备句柄的, 只是不能读写它。你用下面的参数试一试。    

HANDLE hFile = CreateFile(ifDetail->DevicePath,
                  GENERIC_READ | GENERIC_WRITE,
                   FILE_SHARE_WRITE|FILE_SHARE_READ,
.......


谢谢lejianz的热心回复。

我按照你说的方法来获得设备句柄,但是返回的hDevice还是0xffffffff,也就是无效的句柄。十分的不解:(

另外问一下:用HidD_GetHidGuid()获得的Hid Guid在所有人的机子上都是一样的吗?
都是“4d1e55b2-f16f-11cf-88cb-001111000030”,因为我看到别人的提问的帖子中,得到的也是这个值。这个值是正确的吗?可以用来做为函数SetupDiGetClassDevs()的第一个参数吗?
lejianz
驱动中牛
驱动中牛
  • 注册日期2003-03-05
  • 最后登录2023-11-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望145点
  • 贡献值0点
  • 好评度116点
  • 原创分0分
  • 专家分0分
  • 社区居民
10楼#
发布于:2007-09-25 14:44
没错,键盘和鼠标是OS独占设备,但是可以得到设备句柄的, 只是不能读写它。你用下面的参数试一试。    

HANDLE hFile = CreateFile(ifDetail->DevicePath,
                  GENERIC_READ | GENERIC_WRITE,
                   FILE_SHARE_WRITE|FILE_SHARE_READ,
                NULL,
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
                  NULL);
一起交流,共同提高!
allanzhou9527
驱动牛犊
驱动牛犊
  • 注册日期2006-03-01
  • 最后登录2008-01-17
  • 粉丝0
  • 关注0
  • 积分710分
  • 威望72点
  • 贡献值0点
  • 好评度71点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-09-25 09:49
引用第1楼lejianz于2007-09-25 09:20发表的  :
你的问题在于:

  你试图通过HID的GUID得到设备句柄, 但系统中有很多HID设备, 你应做一个循环,让系统做一个N次的查找,得到设备句柄后再读取其它的信息看是不是你想要的设备。


是这样子的,我在前面说明了“通过手动修改Index的值(0,1和2)来分别定位这3个设备”。单步执行的话,可以看到当Index值分别不同时,分别获得了上面三个HID类设备的完整路径。

有网友提示过我,说因为鼠标键盘是标准的输入输出设备(包括我用开发板做的HID设备其实也是个鼠标),它们是系统独占的,用CreateFile是无法获得其句柄的。

我看了USBView的代码后,发现它是可以得到设备句柄的,只是方法似乎跟我上面代码中所写的不同。哪位达人能告诉我USBView的源代码中的获取设备句柄的方式是按照哪种?我没有找到相关的资料。

再次感谢lejianz的回复,谢谢。
lejianz
驱动中牛
驱动中牛
  • 注册日期2003-03-05
  • 最后登录2023-11-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望145点
  • 贡献值0点
  • 好评度116点
  • 原创分0分
  • 专家分0分
  • 社区居民
12楼#
发布于:2007-09-25 09:20
你的问题在于:

  你试图通过HID的GUID得到设备句柄, 但系统中有很多HID设备, 你应做一个循环,让系统做一个N次的查找,得到设备句柄后再读取其它的信息看是不是你想要的设备。
一起交流,共同提高!
游客

返回顶部