From c7f35c3a462aa5eec16d6e2e521e121aa7734bf9 Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Wed, 31 Aug 2011 12:39:02 -0400 Subject: [PATCH] Try opening with sharing mode enabled on Windows if normal open fails. Multiple users have reported the need to pass SHARE_MODE_READ|SHARE_MODE_WRITE to CreateFileA(). It seems that some devices will not open at all if sharing is not requested. This commit makes it so that CreateFileA() will be tried twice, the first time with sharing mode OFF (passing 0x0 to the ShareMode parameter of CreateFileA()), and if that fails, it will try to open the device with share mode ON (passing the above SHARE_MODE_ flags to the ShareMode parameter of CreateFileA()). This will have the following effects: For normal devices: Devices will open as normal. Only one instance can be opened at a time. For devices which require share mode to be on: Devices will now open (they would not open at all before). Multiple instances can be opened. This is less than desirable, but the alternative is that these devices don't open at all. --- windows/hid.cpp | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/windows/hid.cpp b/windows/hid.cpp index 9cffe8d..42411f4 100644 --- a/windows/hid.cpp +++ b/windows/hid.cpp @@ -191,6 +191,37 @@ static void lookup_functions() } #endif +static HANDLE open_device(const char *path) +{ + HANDLE handle; + + /* First, try to open with sharing mode turned off. This will make it so + that a HID device can only be opened once. This is to be consistent + with the behavior on the other platforms. */ + handle = CreateFileA(path, + GENERIC_WRITE |GENERIC_READ, + 0, /*share mode*/ + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,//FILE_ATTRIBUTE_NORMAL, + 0); + + if (handle == INVALID_HANDLE_VALUE) { + /* Couldn't open the device. Some devices must be opened + with sharing enabled (even though they are only opened once), + so try it here. */ + handle = CreateFileA(path, + GENERIC_WRITE |GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, /*share mode*/ + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,//FILE_ATTRIBUTE_NORMAL, + 0); + } + + return handle; +} + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) { BOOL res; @@ -268,13 +299,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); // Open a handle to the device - write_handle = CreateFileA(device_interface_detail_data->DevicePath, - GENERIC_WRITE |GENERIC_READ, - 0x0, /*share mode*/ - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED,//FILE_ATTRIBUTE_NORMAL, - 0); + write_handle = open_device(device_interface_detail_data->DevicePath); // Check validity of write_handle. if (write_handle == INVALID_HANDLE_VALUE) { @@ -472,13 +497,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) dev = new_hid_device(); // Open a handle to the device - dev->device_handle = CreateFileA(path, - GENERIC_WRITE |GENERIC_READ, - 0x0, /*share mode*/ - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED,//FILE_ATTRIBUTE_NORMAL, - 0); + dev->device_handle = open_device(path); // Check validity of write_handle. if (dev->device_handle == INVALID_HANDLE_VALUE) {