internal override void HandleFree() { NativeMethods.CloseHandle(ref _handle); NativeMethods.CloseHandle(ref _closeEventHandle); }
protected override void Run(Action readyCallback) { const string className = "HidSharpDeviceMonitor"; NativeMethods.WindowProc windowProc = DeviceMonitorWindowProc; 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, 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."); 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. IntPtr searchHandle, radioHandle; var searchParams = new NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS() { Size = Marshal.SizeOf(typeof(NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS)) }; searchHandle = NativeMethods.BluetoothFindFirstRadio(ref searchParams, out radioHandle); if (searchHandle != IntPtr.Zero) { do { var radio = new BleRadio(); radio.RadioHandle = radioHandle; radio.NotifyHandle = RegisterDeviceNotification(hwnd, radioHandle); bleHandles.Add(radio); }while (NativeMethods.BluetoothFindNextRadio(searchHandle, out radioHandle)); NativeMethods.BluetoothFindRadioClose(searchHandle); } if (bleHandles.Count > 0) { HidSharpDiagnostics.Trace("Found {0} Bluetooth radio(s).", bleHandles.Count); } #endif //_bleDiscoveryThread = new Thread(BleDiscoveryThread) { IsBackground = true, Name = "HidSharp BLE Discovery" }; //_bleDiscoveryThread.Start(); _serialWatcherShutdownEvent = NativeMethods.CreateManualResetEventOrThrow(); _serialWatcherThread = new Thread(SerialWatcherThread) { IsBackground = true, Name = "HidSharp Serial Watcher" }; _serialWatcherThread.Start(); _hidNotifyObject = new object(); _serNotifyObject = new object(); _bleNotifyObject = new object(); _notifyThread = new Thread(DeviceMonitorEventThread) { IsBackground = true, Name = "HidSharp RaiseChanged" }; _notifyThread.Start(); readyCallback(); NativeMethods.MSG msg; while (true) { int result = NativeMethods.GetMessage(out msg, hwnd, 0, 0); if (result == 0 || result == -1) { break; } NativeMethods.TranslateMessage(ref msg); NativeMethods.DispatchMessage(ref msg); } //lock (_bleDiscoveryThread) { _bleDiscoveryShuttingDown = true; Monitor.Pulse(_bleDiscoveryThread); } lock (_notifyThread) { _notifyThreadShuttingDown = true; Monitor.Pulse(_notifyThread); } NativeMethods.SetEvent(_serialWatcherShutdownEvent); //_bleDiscoveryThread.Join(); _notifyThread.Join(); _serialWatcherThread.Join(); UnregisterDeviceNotification(hidNotifyHandle); UnregisterDeviceNotification(bleNotifyHandle); #if BLUETOOTH_NOTIFY foreach (var bleHandle in bleHandles) { UnregisterDeviceNotification(bleHandle.NotifyHandle); NativeMethods.CloseHandle(bleHandle.RadioHandle); } #endif RunAssert(NativeMethods.DestroyWindow(hwnd), "HidSharp DestroyWindow failed."); RunAssert(NativeMethods.UnregisterClass(className, IntPtr.Zero), "HidSharp UnregisterClass failed."); GC.KeepAlive(windowProc); }