/* WinUSBNet library * (C) 2010 Thomas Bleeker (www.madwizard.org) * * Licensed under the MIT license, see license.txt or: * http://www.opensource.org/licenses/mit-license.php */ using System; namespace MadWizard.WinUSBNet { /// /// Delegate for event handler methods handing USB events /// /// The source of the event /// Details of the event public delegate void USBEventHandler(object sender, USBEvent e); /// /// Event type enumeration for WinUSB events /// public enum USBEventType { /// /// A device has been connected to the system /// DeviceArrival, /// /// A device has been disconnected from the system /// DeviceRemoval, } /// /// Contains the details of a USB event /// public class USBEvent : EventArgs { /// /// WinUSB interface GUID of the device as specified in the WinUSBNotifier /// public Guid Guid; /// /// Device pathname that identifies the device /// public string DevicePath; /// /// Type of event that occurred /// public USBEventType Type; internal USBEvent(USBEventType type, Guid guid, string devicePath) { this.Guid = guid; this.DevicePath = devicePath; this.Type = type; } } /// /// Helper class to receive notifications on USB device changes such as /// connecting or removing a device. /// public class USBNotifier : IDisposable { private DeviceNotifyHook _hook; private Guid _guid; private WPinternals.AsyncAutoResetEvent NodeChangeEvent = new WPinternals.AsyncAutoResetEvent(false); /// /// Event triggered when a new USB device that matches the USBNotifier's GUID is connected /// private event USBEventHandler _Arrival; public event USBEventHandler Arrival { // Heathcliff74 - Also notify currently connected USB devices add { _Arrival -= value; _Arrival += value; USBDeviceInfo[] Devices = USBDevice.GetDevices(Guid); foreach (USBDeviceInfo Device in Devices) _Arrival(this, new USBEvent(USBEventType.DeviceArrival, Guid, Device.DevicePath)); } remove { _Arrival -= value; } } /// /// Event triggered when a new USB device that matches the USBNotifier's GUID is disconnected /// public event USBEventHandler Removal; /// /// The interface GUID of devices this USBNotifier will watch /// public Guid Guid { get { return _guid; } } /// /// Constructs a new USBNotifier that will watch for events on /// devices matching the given interface GUID. A Windows Forms control /// is needed since the notifier relies on window messages. /// /// A control that will be used internally for device notification messages. /// You can use a Form object for example. /// The interface GUID string of the devices to watch. public USBNotifier(string guidString) : this(new Guid(guidString)) { // Handled in other constructor } /// /// Constructs a new USBNotifier that will watch for events on /// devices matching the given interface GUID. A Windows Forms control /// is needed since the notifier relies on window messages. /// /// A control that will be used internally for device notification messages. /// You can use a Form object for example. /// The interface GUID of the devices to watch. public USBNotifier(Guid guid) { _guid = guid; _hook = new DeviceNotifyHook(this, _guid); } /// /// Triggers the arrival event /// /// Device pathname of the device that has been connected protected void OnArrival(string devicePath) { if (_Arrival != null) _Arrival(this, new USBEvent(USBEventType.DeviceArrival, _guid, devicePath)); } /// /// Trigggers the removal event /// /// Device pathname of the device that has been connected protected void OnRemoval(string devicePath) { if (Removal != null) Removal(this, new USBEvent(USBEventType.DeviceRemoval, _guid, devicePath)); } internal int HandleDeviceChange(int msg, IntPtr wParam, IntPtr lParam) { if (msg != API.DeviceManagement.WM_DEVICECHANGE) throw new USBException("Invalid device change message."); // should not happen //switch ((int)wParam) //{ // case API.DeviceManagement.DBT_DEVICEARRIVAL: // WPinternals.LogFile.Log(Guid.ToString() + " - DBT_DEVICEARRIVAL", WPinternals.LogType.FileOnly); // break; // case API.DeviceManagement.DBT_DEVICEREMOVECOMPLETE: // WPinternals.LogFile.Log(Guid.ToString() + " - DBT_DEVICEREMOVECOMPLETE", WPinternals.LogType.FileOnly); // break; // case API.DeviceManagement.DBT_DEVNODES_CHANGED: // WPinternals.LogFile.Log(Guid.ToString() + " - DBT_DEVNODES_CHANGED", WPinternals.LogType.FileOnly); // break; // case API.DeviceManagement.DBT_QUERYCHANGECONFIG: // WPinternals.LogFile.Log(Guid.ToString() + " - DBT_QUERYCHANGECONFIG", WPinternals.LogType.FileOnly); // break; // default: // WPinternals.LogFile.Log(Guid.ToString() + " - wParam: 0x" + ((int)wParam).ToString("X8"), WPinternals.LogType.FileOnly); // break; //} if ((int)wParam == API.DeviceManagement.DBT_DEVICEARRIVAL) { string devName = API.DeviceManagement.GetNotifyMessageDeviceName(lParam, _guid); if (devName != null) OnArrival(devName); } if ((int)wParam == API.DeviceManagement.DBT_DEVICEREMOVECOMPLETE) { string devName = API.DeviceManagement.GetNotifyMessageDeviceName(lParam, _guid); if (devName != null) OnRemoval(devName); } if ((int)wParam == API.DeviceManagement.DBT_DEVNODES_CHANGED) { NodeChangeEvent.Set(); } if ((int)wParam == API.DeviceManagement.DBT_QUERYCHANGECONFIG) { return 1; // Give permission } return 0; } public async System.Threading.Tasks.Task WaitForNextNodeChange() { await NodeChangeEvent.WaitAsync(System.Threading.Timeout.InfiniteTimeSpan); } /// /// Disposes the USBNotifier object and frees all resources. /// Call this method when the object is no longer needed. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Disposes the object's resources. /// /// True when dispose is called manually, false when called by the finalizer. protected virtual void Dispose(bool disposing) { if (disposing) { _hook.Dispose(); } } } }