New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HID open fail in Window 10 #231

Closed
kevintruong opened this Issue Aug 7, 2015 · 19 comments

Comments

Projects
None yet
10 participants
@kevintruong

kevintruong commented Aug 7, 2015

Hi all,
I performed a quick test hidapi in window 10.
That seen have problems in there.
Enumerate HID device is working fine. But FALSE When open device at
dev->device_handle = open_device(path, FALSE);
thelasterror() return 32(ERROR_SHARING_VIOLATION).
Have anyone even test the hpiapi in window 10.
Any suggestion will helpful me.
Thanks and appreciate,
Kevin

@signal11

This comment has been minimized.

Owner

signal11 commented Aug 12, 2015

Play around with the sharing options passed to OpenFile(). Something already has your device open probably.

@dwillbarron

This comment has been minimized.

dwillbarron commented Aug 18, 2015

Windows 10 appears to be instantly opening just about every device under the System process (pid 4). It might be best for the program to be updated to check for Win10 and change the sharing settings, as this quirk is core to the operating system now.

Edit: I can confirm that changing the sharing settings for enumerate=false to SHARE_READ | SHARE_WRITE fixes HIDAPI on Windows 10.

@kevintruong

This comment has been minimized.

kevintruong commented Aug 19, 2015

Hello dwillbarron.
Sr about I can not understand what you mean.
Would like to get more detail about your comment?
Thank

@kevintruong

This comment has been minimized.

kevintruong commented Aug 19, 2015

With the issues. In my program I have changed something by change to open_device2 (Change something in read/write policy). for now it's working with my own open_device2. But I want to know the root cause.
appreciate for your comment.

@dwillbarron

This comment has been minimized.

dwillbarron commented Aug 19, 2015

OK, so basically HID raw input in windows (and all operating systems afaik) can be accessed through a virtual file. That's what HIDAPI is using, and that's what the 'path' property of a device in HIDAPI is referring to—the location of the virtual file. In Windows, the first application that opens a file gets to determine its sharing settings—that is, whether other applications can read, write, or delete the file. The second application can only access the file permissions that are shared, and the specified permissions must exactly match those of what the first application specified, or else the file open operation will fail.

Most applications and libraries accessing HID devices request to share both read and write on the device, but HIDAPI by default only shares access to reading. This is why your HID devices usually disappeared to other applications once HIDAPI was bound to them. These applications tried to request to share both read and write access, were denied, and immediately gave up.

The other result of this is that HIDAPI generally needs to be the first application to request access to a device, as its sharing settings most likely won't match those of other applications. That's what leads to the incompatibility in Windows 10: For whatever reason, the system automatically and immediately opens all HID devices, with its sharing settings set to read and write. Since HIDAPI wants exclusive write access and will only share the read permission, opening the device fails since there's already at least one application that has write permissions. All that needs to be done to fix this is allowing HIDAPI to share write access to the device.

To fix this, I recompiled HIDAPI with a change of one line in hid.c (starting at line 222):
Before:

    DWORD share_mode = (enumerate)?
                          FILE_SHARE_READ|FILE_SHARE_WRITE:
                          FILE_SHARE_READ;

After:

    DWORD share_mode = (enumerate)?
                          FILE_SHARE_READ|FILE_SHARE_WRITE:
                          FILE_SHARE_READ|FILE_SHARE_WRITE;
@albemala

This comment has been minimized.

albemala commented Aug 19, 2015

I confirm the issue and I also confirm that the code from @dwillbarron works.

To clarify further, under windows/hid.c, this is an implementation of open_device function with working code:

static HANDLE open_device2(const char *path)
{
    HANDLE handle;

    handle = CreateFileA(path,
        GENERIC_WRITE | GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        0);

    return handle;
}

The old code was:

static HANDLE open_device(const char *path, BOOL enumerate)
{
    HANDLE handle;
    DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
    DWORD share_mode = (enumerate)?
                          FILE_SHARE_READ|FILE_SHARE_WRITE:
                          FILE_SHARE_READ;

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

    return handle;
}
@kevintruong

This comment has been minimized.

kevintruong commented Aug 19, 2015

Yeah, I got it. Thank you for your patient
Thank and appreciate all of you

@albemala

This comment has been minimized.

albemala commented Aug 19, 2015

I actually think that this code change should be integrated in the codebase, since it's actually a Windows 10 issue... So this thread shouldn't be closed.

@dwillbarron

This comment has been minimized.

dwillbarron commented Aug 19, 2015

Seconded.

@tommy7600

This comment has been minimized.

tommy7600 commented Oct 7, 2015

After this patch i have onlu one from 3 devices avaiable

@juzzlin

This comment has been minimized.

juzzlin commented Nov 2, 2015

I'm having a similar issue on Windows 8.1. The devices are enumerated correctly, but trying to open a device fails. Using that open_device2() above seemed to fix the issue.

@signal11

This comment has been minimized.

Owner

signal11 commented Nov 2, 2015

Yes, opening devices with FILE_SHARE_READ | FILE_SHARE_WRITE papers over all kinds of problems. We've known that for years. Why is Windows 10 holding your device open. That should be the question.

To be specific, using sharing like this doesn't prevent you (or two different applications) from opening the device twice.

@ericharbison

This comment has been minimized.

ericharbison commented Dec 2, 2015

I have the exact same problem you are describing. My application was working in Windows XP, Vista, 7 and 8 just fine. But not in Windows 10. To fix Windows 10, we did the exact same thing that you mentioned.

Old Code broken in Windows 10:

    GENERIC_WRITE | GENERIC_READ,
    FILE_SHARE_READ 

New Code that works in Windows 10:

    GENERIC_WRITE | GENERIC_READ,
    FILE_SHARE_READ | FILE_SHARE_WRITE

The issue with this is that our USB HID device is custom made by us, along with the software. Other 3rd parties have also created software to connect to our HID devices. Having more then one program writing to the HID device causes problems and race conditions. Our original code prevented other applications from writing to the device when our application was running, which seemed to solve the problem. But for some reason in Windows 10, it is requiring that all software have permission to write to a HID device as a shared resource. I'm not sure what Microsoft is thinking here. I'm beginning to think that Microsoft did this intentionally.

@prusnak

This comment has been minimized.

Contributor

prusnak commented Feb 15, 2016

Why is this closed without being merged in? This is one of the issues that contributes to dozens of hidapi forks around Github, which results in dozens of forks of cython-hidapi using custom hidapi forks included as a submodule. Really a sad state. :-/

We can adapt the behaviour depending on the Windows version detected with IsWindows10OrGreater function: https://msdn.microsoft.com/en-us/library/dn905474(v=vs.85).aspx

@signal11

This comment has been minimized.

Owner

signal11 commented Feb 16, 2016

It's because forcing all opens to be in shared mode is not the desired behavior and breaks mutual exclusion. Maybe if Windows is going to mess everything up, we just can't have it that way though.

@meta-meta

This comment has been minimized.

meta-meta commented Feb 17, 2016

So what's the recommended workaround for Win10? Should I rebuild with a forked hidapi?

@rpavlik

This comment has been minimized.

Contributor

rpavlik commented Mar 2, 2016

Ah, wish I had seen this one open, rather than closed as wontfix-windows-is-broken. Code that does what earlier versions of HIDAPI did - that is, first try to exclusively open, and failing that, try the sharing - is in #260 which I submitted for exactly this reason - I was getting failure reports from testers on Windows 10.

@signal11

This comment has been minimized.

Owner

signal11 commented Mar 3, 2016

pushed b5b2e17

I still don't like it, but Windows has forced us into it.

@prusnak

This comment has been minimized.

Contributor

prusnak commented Mar 3, 2016

Thanks! It is not ideal, but I guess it is the best available solution at the moment (until MS guys fix the issue properly).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment