Skip to content
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

Make the hid manager to stop and start listening #37

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions HidSharp/Platform/HidManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ public virtual BleDiscovery BeginBleDiscovery()
throw new NotSupportedException();
}

public virtual void Stop()
{

}

IEnumerable<Device> GetDevices(DeviceTypeInfo type)
{
var _deviceList = type.DeviceList;
Expand Down
56 changes: 44 additions & 12 deletions HidSharp/Platform/HidSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,63 @@ namespace HidSharp.Platform
{
sealed class HidSelector
{
public static bool IsRun;
public static readonly HidManager Instance;
static readonly Thread ManagerThread;
static Thread ManagerThread;

static HidSelector()
{
foreach (var hidManager in new HidManager[]
{
new Windows.WinHidManager(),
new Linux.LinuxHidManager(),
new MacOS.MacHidManager(),
new Unsupported.UnsupportedHidManager()
})
{
new Windows.WinHidManager(),
new Linux.LinuxHidManager(),
new MacOS.MacHidManager(),
new Unsupported.UnsupportedHidManager()
})
{
if (hidManager.IsSupported)
{
var readyEvent = new ManualResetEvent(false);

Instance = hidManager;
Instance.InitializeEventManager();
ManagerThread = new Thread(Instance.RunImpl) { IsBackground = true, Name = "HID Manager" };
ManagerThread.Start(readyEvent);
readyEvent.WaitOne();
InitManager();
break;
}
}
}

public static void InitManager()
{
var readyEvent = new ManualResetEvent(false);

ManagerThread = new Thread(Instance.RunImpl) { IsBackground = true, Name = "HID Manager" };
ManagerThread.Start(readyEvent);
readyEvent.WaitOne();
IsRun = true;
}

public static void Stop()
{
Instance?.Stop();
IsRun = false;
}
}

public static class HidSelectorManager
{
public static void Stop()
{
if (HidSelector.IsRun)
{
HidSelector.Stop();
}
}

public static void Start()
{
if (!HidSelector.IsRun)
{
HidSelector.InitManager();
}
}
}
}
11 changes: 9 additions & 2 deletions HidSharp/Platform/Linux/LinuxHidManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ namespace HidSharp.Platform.Linux
{
sealed class LinuxHidManager : HidManager
{
private bool _isStop;

protected override SystemEvents.EventManager CreateEventManager()
{
return new SystemEvents.LinuxEventManager();
Expand Down Expand Up @@ -60,8 +62,8 @@ protected override void Run(Action readyCallback)
readyCallback();
while (true)
{
ret = NativeMethods.retry(() => NativeMethods.poll(ref pfd, (IntPtr)1, -1));
if (ret < 0) { break; }
ret = NativeMethods.retry(() => NativeMethods.poll(ref pfd, (IntPtr)1, 1000));
if (ret < 0 || _isStop) { break; }

if (ret == 1)
{
Expand Down Expand Up @@ -172,6 +174,11 @@ protected override bool TryCreateSerialDevice(object key, out Device device)
device = LinuxSerialDevice.TryCreate((string)key); return true;
}

public override void Stop()
{
_isStop = true;
}

public override string FriendlyName
{
get
Expand Down
20 changes: 15 additions & 5 deletions HidSharp/Platform/MacOS/MacHidManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace HidSharp.Platform.MacOS
{
sealed class MacHidManager : HidManager
{
private IntPtr _runLoop;

protected override SystemEvents.EventManager CreateEventManager()
{
return new SystemEvents.MacOSEventManager();
Expand All @@ -43,18 +45,18 @@ protected override void Run(Action readyCallback)
NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(manager.Handle, devicesChangedCallback, IntPtr.Zero);
NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(manager.Handle, devicesChangedCallback, IntPtr.Zero);

var runLoop = NativeMethods.CFRunLoopGetCurrent();
NativeMethods.CFRetain(runLoop);
NativeMethods.IOHIDManagerScheduleWithRunLoop(manager, runLoop, NativeMethods.kCFRunLoopDefaultMode);
_runLoop = NativeMethods.CFRunLoopGetCurrent();
NativeMethods.CFRetain(_runLoop);
NativeMethods.IOHIDManagerScheduleWithRunLoop(manager, _runLoop, NativeMethods.kCFRunLoopDefaultMode);
try
{
readyCallback();
NativeMethods.CFRunLoopRun();
}
finally
{
NativeMethods.IOHIDManagerUnscheduleFromRunLoop(manager, runLoop, NativeMethods.kCFRunLoopDefaultMode);
NativeMethods.CFRelease(runLoop);
NativeMethods.IOHIDManagerUnscheduleFromRunLoop(manager, _runLoop, NativeMethods.kCFRunLoopDefaultMode);
NativeMethods.CFRelease(_runLoop);
}

GC.KeepAlive(devicesChangedCallback);
Expand Down Expand Up @@ -131,6 +133,14 @@ protected override bool TryCreateSerialDevice(object key, out Device device)
return device != null;
}

public override void Stop()
{
if (_runLoop != IntPtr.Zero)
{
NativeMethods.CFRunLoopStop(_runLoop);
}
}

public override string FriendlyName
{
get { return "Mac OS HID"; }
Expand Down
4 changes: 4 additions & 0 deletions HidSharp/Platform/Windows/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ unsafe static class NativeMethods
public const uint WAIT_OBJECT_1 = 1;
public const uint WAIT_TIMEOUT = 258;
public const uint WM_DEVICECHANGE = 537;
public const uint WM_CLOSE = 0x0010;

public const uint RTS_CONTROL_DISABLE = 0;
public const uint RTS_CONTROL_ENABLE = 1;
Expand Down Expand Up @@ -1004,6 +1005,9 @@ public static extern IntPtr CreateWindowEx(uint exStyle,
[DllImport("user32.dll")]
public static extern int GetMessage(out MSG message, IntPtr window, uint messageMin, uint messageMax);

[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr window, uint message, IntPtr messageMin, IntPtr messageMax);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool TranslateMessage(ref MSG message);
Expand Down
24 changes: 17 additions & 7 deletions HidSharp/Platform/Windows/WinHidManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public override int GetHashCode()
bool _isSupported;
bool _bleIsSupported;

IntPtr _hwnd;

//static Thread _bleDiscoveryThread;
//static int _bleDiscoveryRefCount;
//static volatile bool _bleDiscoveryShuttingDown;
Expand Down Expand Up @@ -158,14 +160,14 @@ protected override void Run(Action readyCallback)
var wc = new NativeMethods.WNDCLASS() { ClassName = className, WindowProc = windowProc };
RunAssert(0 != NativeMethods.RegisterClass(ref wc), "HidSharp RegisterClass failed.");

var hwnd = NativeMethods.CreateWindowEx(0, className, className, 0,
_hwnd = NativeMethods.CreateWindowEx(0, className, className, 0,
NativeMethods.CW_USEDEFAULT, NativeMethods.CW_USEDEFAULT, NativeMethods.CW_USEDEFAULT, NativeMethods.CW_USEDEFAULT,
NativeMethods.HWND_MESSAGE,
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
RunAssert(hwnd != IntPtr.Zero, "HidSharp CreateWindow failed.");
RunAssert(_hwnd != IntPtr.Zero, "HidSharp CreateWindow failed.");

var hidNotifyHandle = RegisterDeviceNotification(hwnd, NativeMethods.HidD_GetHidGuid());
var bleNotifyHandle = RegisterDeviceNotification(hwnd, NativeMethods.GuidForBluetoothLEDevice);
var hidNotifyHandle = RegisterDeviceNotification(_hwnd, NativeMethods.HidD_GetHidGuid());
var bleNotifyHandle = RegisterDeviceNotification(_hwnd, NativeMethods.GuidForBluetoothLEDevice);

#if BLUETOOTH_NOTIFY
var bleHandles = new List<BleRadio>(); // FIXME: We don't handle the removal of USB Bluetooth dongles here, as far as notifications go.
Expand Down Expand Up @@ -212,8 +214,8 @@ protected override void Run(Action readyCallback)
NativeMethods.MSG msg;
while (true)
{
int result = NativeMethods.GetMessage(out msg, hwnd, 0, 0);
if (result == 0 || result == -1) { break; }
int result = NativeMethods.GetMessage(out msg, _hwnd, 0, 0);
if (result == 0 || result == -1 || msg.Message == NativeMethods.WM_CLOSE) { break; }

NativeMethods.TranslateMessage(ref msg);
NativeMethods.DispatchMessage(ref msg);
Expand All @@ -232,7 +234,7 @@ protected override void Run(Action readyCallback)
foreach (var bleHandle in bleHandles) { UnregisterDeviceNotification(bleHandle.NotifyHandle); NativeMethods.CloseHandle(bleHandle.RadioHandle); }
#endif

RunAssert(NativeMethods.DestroyWindow(hwnd), "HidSharp DestroyWindow failed.");
RunAssert(NativeMethods.DestroyWindow(_hwnd), "HidSharp DestroyWindow failed.");
RunAssert(NativeMethods.UnregisterClass(className, IntPtr.Zero), "HidSharp UnregisterClass failed.");
GC.KeepAlive(windowProc);
}
Expand Down Expand Up @@ -663,6 +665,14 @@ protected override bool TryCreateSerialDevice(object key, out Device device)
device = WinSerialDevice.TryCreate(path.DevicePath, path.FileSystemName, path.FriendlyName); return true;
}

public override void Stop()
{
if (_hwnd != IntPtr.Zero)
{
RunAssert(NativeMethods.PostMessage(_hwnd, NativeMethods.WM_CLOSE, 0, 0), "HidSharp PostMessage failed.");
}
}

public override bool AreDriversBeingInstalled
{
get
Expand Down