From 0bf98975c85f37b6738db4163495b7d4144c1d32 Mon Sep 17 00:00:00 2001 From: X9VoiD Date: Thu, 30 Jul 2020 20:56:19 +0800 Subject: [PATCH] Add DeviceExclusive to OpenOption --- HidSharp/OpenOption.cs | 7 +++++++ HidSharp/Platform/Linux/LinuxHidDevice.cs | 2 +- HidSharp/Platform/Linux/LinuxHidStream.cs | 11 +++++++---- HidSharp/Platform/MacOS/MacHidDevice.cs | 2 +- HidSharp/Platform/MacOS/MacHidStream.cs | 9 +++++++-- HidSharp/Platform/MacOS/NativeMethods.cs | 3 ++- HidSharp/Platform/Windows/WinHidDevice.cs | 2 +- HidSharp/Platform/Windows/WinHidStream.cs | 8 ++++++-- 8 files changed, 32 insertions(+), 12 deletions(-) diff --git a/HidSharp/OpenOption.cs b/HidSharp/OpenOption.cs index 11f9205..a896bcf 100644 --- a/HidSharp/OpenOption.cs +++ b/HidSharp/OpenOption.cs @@ -40,6 +40,8 @@ public sealed class OpenOption /// public static OpenOption Exclusive { get; private set; } + public static OpenOption DeviceExclusive { get; private set; } + /// /// Allow other processes to send interruption requests. /// If another other process with higher priority attempts to open the HID device this process is using, @@ -86,6 +88,11 @@ static OpenOption() { _options = new Dictionary(); + DeviceExclusive = OpenOption.New(new Guid("{79F41C23-C92C-47C7-8F8C-152127EF9822}"), + deserializeCallback: DeserializeBoolean, + serializeCallback: SerializeBoolean, + defaultValue: false, + friendlyName: "DeviceExclusive"); Exclusive = OpenOption.New(new Guid("{49DB23CD-727E-4788-BBAD-7D67ACCBC469}"), deserializeCallback: DeserializeBoolean, serializeCallback: SerializeBoolean, diff --git a/HidSharp/Platform/Linux/LinuxHidDevice.cs b/HidSharp/Platform/Linux/LinuxHidDevice.cs index f31c61d..a60696b 100644 --- a/HidSharp/Platform/Linux/LinuxHidDevice.cs +++ b/HidSharp/Platform/Linux/LinuxHidDevice.cs @@ -107,7 +107,7 @@ protected override DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig) RequiresGetInfo(); var stream = new LinuxHidStream(this); - try { stream.Init(_path); return stream; } + try { stream.Init(_path, openConfig); return stream; } catch { stream.Close(); throw; } } diff --git a/HidSharp/Platform/Linux/LinuxHidStream.cs b/HidSharp/Platform/Linux/LinuxHidStream.cs index cd974b1..e8dfeea 100644 --- a/HidSharp/Platform/Linux/LinuxHidStream.cs +++ b/HidSharp/Platform/Linux/LinuxHidStream.cs @@ -89,12 +89,15 @@ internal static int DeviceHandleFromPath(string path, HidDevice hidDevice, Nativ throw new FileNotFoundException("HID class device not found."); } - internal void Init(string path) + internal void Init(string path, OpenConfiguration openConfig) { int handle; - handle = DeviceHandleFromPath(path, Device, NativeMethods.oflag.RDWR | NativeMethods.oflag.NONBLOCK); - - _handle = handle; + if ((bool)openConfig.GetOption(OpenOption.DeviceExclusive)) + handle = DeviceHandleFromPath(path, Device, NativeMethods.oflag.RDWR | NativeMethods.oflag.EXCL); + else + handle = DeviceHandleFromPath(path, Device, NativeMethods.oflag.RDWR | NativeMethods.oflag.NONBLOCK); + + _handle = handle; HandleInitAndOpen(); _readThread.Start(); diff --git a/HidSharp/Platform/MacOS/MacHidDevice.cs b/HidSharp/Platform/MacOS/MacHidDevice.cs index a5685e4..cec5f77 100644 --- a/HidSharp/Platform/MacOS/MacHidDevice.cs +++ b/HidSharp/Platform/MacOS/MacHidDevice.cs @@ -123,7 +123,7 @@ internal static MacHidDevice TryCreate(NativeMethods.io_string_t path) protected override DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig) { var stream = new MacHidStream(this); - try { stream.Init(_path); return stream; } + try { stream.Init(_path, openConfig); return stream; } catch { stream.Close(); throw; } } diff --git a/HidSharp/Platform/MacOS/MacHidStream.cs b/HidSharp/Platform/MacOS/MacHidStream.cs index 75a497d..de69f02 100644 --- a/HidSharp/Platform/MacOS/MacHidStream.cs +++ b/HidSharp/Platform/MacOS/MacHidStream.cs @@ -44,7 +44,7 @@ internal MacHidStream(MacHidDevice device) _writeThread = new Thread(WriteThread) { IsBackground = true, Name = "HID Writer" }; } - internal void Init(NativeMethods.io_string_t path) + internal void Init(NativeMethods.io_string_t path, OpenConfiguration openConfig) { IntPtr handle; int retryCount = 0, maxRetries = 10; while (true) @@ -59,7 +59,12 @@ internal void Init(NativeMethods.io_string_t path) handle = NativeMethods.IOHIDDeviceCreate(IntPtr.Zero, service); if (handle != IntPtr.Zero) { - var ret = NativeMethods.IOHIDDeviceOpen(handle); + NativeMethods.IOReturn ret; + if ((bool)openConfig.GetOption(OpenOption.DeviceExclusive)) + ret = NativeMethods.IOHIDDeviceOpen(handle, NativeMethods.IOOptionBits.SeizeDevice); + else + ret = NativeMethods.IOHIDDeviceOpen(handle, NativeMethods.IOOptionBits.None); + if (ret == NativeMethods.IOReturn.Success) { break; } NativeMethods.CFRelease(handle); diff --git a/HidSharp/Platform/MacOS/NativeMethods.cs b/HidSharp/Platform/MacOS/NativeMethods.cs index d2fdf2c..f007f05 100644 --- a/HidSharp/Platform/MacOS/NativeMethods.cs +++ b/HidSharp/Platform/MacOS/NativeMethods.cs @@ -128,7 +128,8 @@ public enum OSType : uint public enum IOOptionBits { - None = 0 + None = 0, + SeizeDevice = 1 } public enum IOHIDElementType diff --git a/HidSharp/Platform/Windows/WinHidDevice.cs b/HidSharp/Platform/Windows/WinHidDevice.cs index e1e4968..d6e357e 100644 --- a/HidSharp/Platform/Windows/WinHidDevice.cs +++ b/HidSharp/Platform/Windows/WinHidDevice.cs @@ -77,7 +77,7 @@ protected override DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig) RequiresGetInfo(GetInfoFlags.ReportInfo); var stream = new WinHidStream(this); - try { stream.Init(_path); return stream; } + try { stream.Init(_path, openConfig); return stream; } catch { stream.Close(); throw; } } diff --git a/HidSharp/Platform/Windows/WinHidStream.cs b/HidSharp/Platform/Windows/WinHidStream.cs index 3e0aeac..9e871a5 100644 --- a/HidSharp/Platform/Windows/WinHidStream.cs +++ b/HidSharp/Platform/Windows/WinHidStream.cs @@ -40,9 +40,13 @@ internal WinHidStream(WinHidDevice device) NativeMethods.CloseHandle(_closeEventHandle); } - internal void Init(string path) + internal void Init(string path, OpenConfiguration openConfig) { - IntPtr handle = NativeMethods.CreateFileFromDevice(path, NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write, NativeMethods.EFileShare.Read | NativeMethods.EFileShare.Write); + IntPtr handle; + if ((bool)openConfig.GetOption(OpenOption.DeviceExclusive)) + handle = NativeMethods.CreateFileFromDevice(path, NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write, NativeMethods.EFileShare.None); + else + handle = NativeMethods.CreateFileFromDevice(path, NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write, NativeMethods.EFileShare.Read | NativeMethods.EFileShare.Write); if (handle == (IntPtr)(-1)) { throw DeviceException.CreateIOException(Device, "Unable to open HID class device (" + path + ").");