首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CreateFileA无法在Windows中打开HID设备

CreateFileA无法在Windows中打开HID设备
EN

Stack Overflow用户
提问于 2016-05-13 15:13:10
回答 2查看 4.1K关注 0票数 10

编辑:在这里报道的问题:https://github.com/signal11/hidapi/issues/276

墨水是Wacom公司的钢笔设备。(InklingReader)是一个开源项目,从它获取实时数据。

我正在整理InklingReader以使用HIDAPI而不是libusb (因为它在更高的层次上工作: HID而不是原始的USB,所以更紧凑&更适合)。另外,libusb在最近的OSX上也失败了。

HID是一个小库:一个.h,一个(每个平台) .c.

我的代码如下所示:

代码语言:javascript
运行
复制
    unsigned short  inklingVendorId = 0x056a, inklingProductId = 0x0221;
    if (hid_init() == FAIL) return;   
    handle = hid_open(inklingVendorId, inklingProductId, nullptr);

在Windows hid_open上失败。单步显示故障点这里

代码语言:javascript
运行
复制
// path = "\\\\?\\hid#vid_056a&pid_0221&mi_00&col01#8&1ea90857&0&0000#"
//        "{4d1e55b2-f16f-11cf-88cb-001111000030}"
//
static HANDLE open_device(const char *path, BOOL enumerate)
{
    HANDLE handle;
    DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
    DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;

    // enumerate = 0
    handle = CreateFileA(path,
        desired_access,
        share_mode,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
        0);

    int err = GetLastError(); // 5 i.e. ERROR_ACCESS_DENIED

    return handle; // returns 0xffffffff i.e. INVALID_HANDLE
}

现在,HIDAPI作者说:"HIDAPI不能在Windows上使用键盘和鼠标。Windows作为一种安全措施,不允许打开鼠标和键盘HID。“(这里)

如果我列举HID装置:

代码语言:javascript
运行
复制
    struct hid_device_info *devs, *cur_dev;

    devs = hid_enumerate(inklingVendorId, inklingProductId);
    cur_dev = devs;
    while (cur_dev) {
        DBG2("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
        DBG2("");
        DBG2("  Manufacturer: %ls", cur_dev->manufacturer_string);
        DBG2("  Product:      %ls", cur_dev->product_string);
        DBG2("  Release:      %hx", cur_dev->release_number);
        DBG2("  Interface:    %d",  cur_dev->interface_number);
        DBG2("  Usage Page:   %d", cur_dev->usage_page);
        DBG2("  Usage:        %d", cur_dev->usage);
        DBG2("");
        cur_dev = cur_dev->next;
    }
    hid_free_enumeration(devs);

..。我收到的不是一条而是两条:

代码语言:javascript
运行
复制
Device Found
  type: 056a 0221
  path: \\?\hid#vid_056a&pid_0221&mi_00&col01#8&1ea90857&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
  serial_number: 2B0400001C90C22A0002DD07FE8B022A

  Manufacturer: Wacom, Inc.
  Product:      MSC Device
  Release:      1256
  Interface:    0
  Usage Page:   1
  Usage:        2

Device Found
  type: 056a 0221
  path: \\?\hid#vid_056a&pid_0221&mi_00&col02#8&1ea90857&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}
  serial_number: 2B0400001C90C22A0002DD07FE8B022A

  Manufacturer: Wacom, Inc.
  Product:      MSC Device
  Release:      1256
  Interface:    0
  Usage Page:   13
  Usage:        2

(注: OSX只报告第二项!)在OSX上没有问题!)

比较path

路径:\?\hid#vid_056a&pid_0221&mi_00&col01#8&1ea90857&0&0000#...

路径:\?\hid#vid_056a&pid_0221&mi_00&col02#8&1ea90857&0&0001#...

根据12v2.pdf的说法,

UsagePage/Usage = 1/2 = {Generic控件}/{老鼠}。

UsagePage/Usage = 13/2 ={数字化者}/{Pen}。

(编辑:有时第一条路径是1/2,第二条路径是13/2,有时是交换路径)。

HIDAPI是只拿了它找到的第一个

所以看起来这应该是解决办法。墨水暴露了2‘设备’和隐藏是错误的(鼠标)一个,而Windows不允许访问鼠标或键盘设备。

所以我修改了密码..。

代码语言:javascript
运行
复制
while (cur_dev) {
    if (cur_dev->vendor_id == vendor_id &&
        cur_dev->product_id == product_id &&
        cur_dev->usage_page == 13) 
    {

..。为了得到正确的条目,它应该工作对吗?

不,CreateFileA只是引发了一个不同的错误:

usage_page== 1 =>错误代码5 (ERROR_ACCESS_DENIED)

usage_page==13 =>错误代码32 (ERROR_SHARING_VIOLATION)

嗯。这是相当令人沮丧的。我好像到了死胡同!

我尝试过使用CreateFileA的params,例如用GENERIC_READ | GENERIC_WRITE替换STANDARD_RIGHTS_READ | STANDARD_RIGHTS_WRITE --现在它愉快地创建了一个句柄。但随后的hid_read-s未能收集任何数据。

在谷歌上,https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/af869f90-7bda-483d-ba2d-51680073fe9f/createfile-returns-invalid-handle-while-trying-to-access-hid-device-on-windows-8-desktop-app?forum=wdk似乎包含了一些建议的解决办法:

烤面包机萤火虫都可以在HID堆栈中工作。烤面包机展示了如何通过一个原始的PDO来处理过滤器,萤火虫展示了如何使用WMI访问它。从C的角度来看,我认为原始的PDO要简单得多,WMI有点麻烦和复杂。

萤火虫

烤面包机

作者在烤面包机中推荐了一些东西,但它是一个很大的CodeBase,我没有的经验。

看起来,我似乎要在许多非常陌生的领域中挖掘,才能让任何东西发挥作用,因此,在开始之前,我在这里提出要求。如果没有人回答,我就回答我自己的问题。

我唯一能想到的另一件事是,也许另一个过程已经开始走这条路了。也许如果我能终止这个过程,CreateFileA可能会成功吗?Roel的libusb方法涉及分离内核驱动程序:https://github.com/roelj/inklingreader/blob/master/src/usb/online-mode.c#L98

在我读到的某个地方,如果另一个进程已经打开了这个设备,我们的open必须与这个先前打开的权限相匹配。我还读到Windows会在检测到所有HID设备时自动打开。

找出哪个进程在USB设备句柄上有独占锁。

可能有一个想法是尝试另一种HID库在Windows上与usb设备通信的最佳usb库是什么?

PPPS也许我需要以管理员的身份运行我的代码。但这不是个好办法。

EN

回答 2

Stack Overflow用户

发布于 2016-11-21 15:04:39

我也见过类似的行为。ERROR_SHARING_VIOLATION问题在升级到Windows10周年版后开始发生。这个问题只出现在Windows启动时连接的USB设备上。如果在Windows启动后拔掉并插入USB设备,那么CreateFile就成功了。我还没有找到根本原因或解决办法。

票数 1
EN

Stack Overflow用户

发布于 2020-10-26 12:08:21

你说得对:如果其他应用程序已经打开了这个设备,ERROR_SHARING_VIOLATION就会出现。您需要像这样调用CreateFileW API:

代码语言:javascript
运行
复制
DWORD desired_access = GENERIC_WRITE | GENERIC_READ;
DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
::CreateFileW(deviceInterfacePath, desired_access, share_mode, 0, OPEN_EXISTING, 0, 0);

如果你不提供dwShareMode,那就意味着你只想打开设备。如果其他应用程序(可能本地支持这类设备的新Windows版本)已经打开该设备供其使用,该应用程序可能会失败。

关于键盘和鼠标设备的注释:您也可以调用::CreateFileW,甚至无需设置desired_access (使用零值):在本例中,您可以使用带有返回句柄的HID方法(以及其他一些方法)。但是您不能将数据读写到这种设备上。如果您需要获取HID键盘/鼠标的名称或VID/PID,这将非常有用。

这是Windows下HID设备类型及其访问模式列表

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37213634

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档