GithubHelp home page GithubHelp logo

jinjinov / usb.events Goto Github PK

View Code? Open in Web Editor NEW
90.0 7.0 23.0 308 KB

Subscribe to the Inserted and Removed events to be notified when a USB drive is plugged in or unplugged, or when a USB device is connected or disconnected. Usb.Events is a .NET Standard 2.0 library and uses WMI on Windows, libudev on Linux and IOKit on macOS.

License: MIT License

C# 64.57% C 32.51% Makefile 1.52% Shell 1.41%
usb events net-standard windows linux macos wmi libudev iokit

usb.events's People

Contributors

frankh67 avatar jinjinov avatar maskimthedog avatar robkrakora avatar sinryou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

usb.events's Issues

Missing existing device metadata while running in docker, until device is removed and then added

I have downloaded your latest version 11.1.0.1 and it is working GREAT on the Raspberry PI....THANK YOU for all your effort on issue #29

Now, I am trying to run the application within a docker container. When the application first loads up, I list out all the connected devices. When the devices are listed they are missing all the meta data, but I need the device information when the container is first turned on for all the connected devices:
image

Within the container, if I unplug and plug in the device, the meta data shows up during the add event (but not until i remove and add the device):
image

However, when i run it directly on the PI, the data shows up immediately when the program starts.
image

Interestingly, in both scenarios (container and on pi directly) the existing device counts are 0 and then all the devices get "Added"

My containers Image is based on mcr.microsoft.com/dotnet/runtime:7.0.15-bullseye-slim-arm64v8
and then i install udev and setup some udev rules:

RUN apt-get update -y && \
apt-get install -y udev usbutils && \
echo '\
ACTION=="add", RUN+="mknod %N c %M %m"\n\
ACTION=="remove", RUN+="rm %N"\n\
' > /etc/udev/rules.d/99-togglePico.rules

The container is run in privilege mode. My understanding is that if i run in privilege mode, I dont have to map any devices or volumes but maybe i am wrong.
sudo docker run -it --privileged usb_test_image

and the udev service is restarted before my program is run:
cmd service udev restart && ./USBDetectionTesting

I suspect I am missing some basic dependency in the container but cant figure out what i am missing so your code can find the meta data of the existing devices.

Any help/insight would be appreciated.

No events or device list on macOS

Library version

10.0.1.1

OS & OS version

macOS Monterey Version 12.4

Describe the bug

No events are invoked on macOS when USB devices are added or removed, and the list of USB devices is always empty.

To Reproduce

You can reproduce the issue with the following public repo on GitHub:
https://github.com/hunsra/UsbEventsTest

Steps to reproduce the behavior:

  1. Clone the repository above.
  2. Open the repository with Visual Studio for Mac version 17.0.1 (build 72).
  3. Select the Debug configuration and build the solution. Note that you will see in the build output the following warning, which may be a clue to what is happening:
MMP : warning MM2006: Native library 'UsbEventWatcher.Linux.so' was referenced but could not be found.
MMP : warning MM2006: Native library 'UsbEventWatcher.Mac.dylib' was referenced but could not be found.
    2 Warning(s)
    0 Error(s)
  1. Run the program and attach a USB device to the Mac computer you are running the program on.

Exceptions (if any)

Expected behavior

Based on the description of the library, I should see a list of attached devices in the debugger output window when the program starts, and I should see debugger output when USB devices are added or removed.

Additional context

My suspicion is that the mac and linux native libraries are not included in the NuGet package, or there is a path issue in the NuGet package configuration.

Feature Request: Provide a way to toggle debug logging without relying on the DEBUG preprocessor directive

Is your feature request related to a problem? Please describe.

A large amount of text is always written to the debug output if the DEBUG preprocessor directive is defined. That is to say, if you are debugging a program then you will always see this text, regardless of if it is of any interest.

Describe the solution you'd like

Perhaps a settable bool with a default value of true could be checked on entering the logging methods.

Describe alternatives you've considered

No way to set a preprocessor directive by namespace. Can only be changed per file by modifying the source.

false "device added" events are fired on Linux

Library version

10.0.0

OS & OS version

Ubuntu 18.04 LTS

Describe the bug

When i unplug my USB device from Linux machine i am seeing Usb.Events fire an UsbDeviceAdded event.
I monitored udev events on the Linux machine using "udevadm monitor -e" and I can clearly see that no "add" events are generated. I see "remove" and "unbind" events only.

In your code in UsbEventWatcher.Linux.c line 141, i assume that if event isn't a "remove" then it must be an "add", which as you can see is a bug.
Could you please fix this and publish and updated Nuget please, basically just need to put in a check like this:
(strcmp(action, "remove") == 0 || strcmp(action, "unbind") == 0)

Otherwise, great library and thanks for writing it.

To Reproduce

reproducing this should be easy at least on Ubuntu 18.04. Not sure about other distros...

Inside the windows service this package not working

Library version

10.0.0.0

OS & OS version

Windows 10 Pro & 21H1

Describe the bug

Inside the windows service it does not trigger any events with this package.

When we tested this package, it worked in the console application. But this does not work within the Windows services. Is there are any restrictions for this to work inside the Windows services?

To Reproduce

  • Create a new Windows service project
  • Add the NuGet package USB. Events then initialize the functionality inside the OnStart event
  • But the events were not triggered, to track the function we used the event logger but there are no logs in the event viewer.

Does not work on Windows with .NET 7

I've tested the latest nuget 10.0.1.1 on Linux and Windows with the code example from the README.md.

On Linux, I get UsbDeviceAdded and UsbDeviceRemoved events when I plug and unplug, for instance, a FTDI device or a Bluetooth dongle.

On Windows, no events are triggered. Instead, my notebook fan spins up, as soon as I plug or unplug a USB device. In the task manager I can see the task WMI Provider Host with a huge CPU load and "Very High" power consumption. This stops as soon as I press enter to close the example program. This is reproducible on my machine.

I'm using .NET 7.0 and my csproj of the example program sets the TargetFramework to net7.0.

If I just add Usb.Events as package reference, then I get System.Management 4.7.0 as requested by Usb.Events. To see if there is any difference with the version from .NET 7, I've additionally added System.Management 7.0.0 as package reference to my csproj file of the example program and called dotnet restore. Now, the latest version is installed but without any effect. With both versions, 4.7.0 and 7.0.0, I get the behavior described above.

What I'm doing wrong?

Memory Leak

On line 245 of UsbEventWatcher.Linux.c there appears to be a memory leak. 'dev' is never unreferenced in GetLinuxMountPoint(). I noticed allocated memory ticking up in my test application. I looked over the code and noticed the aforementioned.

IUsbEventWatcher Events not working on WinForms

Library version
10.0.0.0
OS & OS version
Windows NT 10.0
Describe the bug
When you use any event in IUsbEventWatcher you might get a TargetInvocationException,
This bug really needs to be fixed, Console apps work fine aswell.

To Reproduce
Steps to reproduce the behavior:

  1. Use the UsbDriveMounted event and write MessageBox.Show("Mounted: " + path) in that event
  2. Run your application

Expected behavior
I have expected to get the message box saying 'Mounted: D:'
But nothing happens when a drive is mounted

Triggering events works only two times under windows

Library version

10.1.0.1

OS & OS version

Windows 10

Describe the bug

Hello all,

I am using your Nuget Package in my application to determine if specific USB-devices are added or removed. On Windows I have the problem that this functionality works only two times and after that the event is not triggered anymore. Is this a known issue or what could be responsible for this?

To Reproduce

public void WatchUsbActions()
    {
        _usbEventWatcher.UsbDeviceRemoved += (_, device) =>
        {
            // Detect, if we know the device
            var type = ReaderType.IdentifyReader(device.DeviceName);

            // locking variable, set to true, after application is fully initialized
            if (_usbEventProcessingEnabled)
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    // locking variable to prevent multiple events after device removal
                    if (!_notifiedLock)
                    {
                        _notifiedLock = true;

                        Task.Delay(UsbEventDelay).ContinueWith(t => OnReaderChanged?.Invoke(this, false));
                        Task.Delay(500).ContinueWith(t => _notifiedLock = false); //renable event broadcast
                    }
                }
                else
                {
                    if (type == ReaderType.Unknown)
                    {
                        return;
                    }

                    Task.Delay(UsbEventDelay).ContinueWith(t => OnReaderChanged?.Invoke(this, false));
                }
            }
        };
        _usbEventWatcher.UsbDeviceAdded += (_, device) =>
        {
            // Identify device
            var type = ReaderType.IdentifyReader(device.DeviceName);
            if (type == ReaderType.Unknown)
            {
                return;
            }

            if (_usbEventProcessingEnabled)
            {
                Task.Delay(UsbEventDelay).ContinueWith(t => OnReaderChanged?.Invoke(this, true));
            }
        };

Expected behavior

I expect the events UsbDeviceRemoved and UsbDeviceAdded to be triggered on every usb change

Can we allow the monitor loop to exit?

Hi there,

In function MonitorDevices there is a loop to 'select' on the udev fd, which works well but there is no way to exit from this loop. So once StartLinuxWatcher is called we can never stop the wrapping task created by UsbEventWatcher.Start. This is not so good if we want to the monitoring to stop at some point of the program. It also forces the instance of UsbEventWatcher to be a singleton otherwise there might be multiple loops active at the same time and report USB events repeatedly.

I'm wondering, maybe we can add a returning value to UsbDeviceCallback (which returns void by now), and exit from the loop upon a specific value.

Is this a good idea? If yes I can riase a PR.

Regards,

Separate UsbEventWatcher construction from start of enumerating devices

Library version

10.0.1

OS & OS version

Ubuntu 18.04 LTS

Describe the bug

This is kind of a bug or more like a race condition.
Since we have to new up UsbEventWatcher before we can subscribe to UsbDeviceAdded event. It is possible that some device will be missed in the event subscriber because UsbEventWatcher constructor already starts enumerating devices in a background thread.

Suggestion

Could you please separate construction of UsbEventWatcher from start of enumerating devices.
Constructor could just not call the Start method and you could simply make the Start method public and let user call it after they finished subscribing to all the desired events.

An even better option would be to separate EnumerateDevices from StartMonitoring into separate public methods.
And make EnumerateDevices populate the UsbDevicesList instead of firing UsbDeviceAdded event. This way it is more natural to use the library.
You can new up UsbEventWatcher, then EnumerateDevices to get a list of all currently known devices, then StartMonitor to monitor for changes to devices current and new.

Support for 32 bit Raspberry Pi OS

Thank you for the library....i was using it on Windows and it is very nice....easy to use and works as expected. Much appreciated.

I am wanting to use it on a Raspberry Pi, compiling the test project with .Net 6 (I see that the project is compatible with .Net Core 2 and higher) but when i execute the test program, i find no usb devices. I have a mouse, keyboard, and a Raspberry Pico plugged in. Here is my test project.....


using IUsbEventWatcher usbEventWatcher = new UsbEventWatcher(startImmediately: true, addAlreadyPresentDevicesToList: true, usePnPEntity: true, includeTTY: true);

Console.WriteLine("Iterating over existing usb devices: " + usbEventWatcher.UsbDeviceList.Count());

foreach (var device in usbEventWatcher.UsbDeviceList)
{
    Console.WriteLine($"{DateTime.Now} Existing:" + Environment.NewLine + device + Environment.NewLine);
}
Console.WriteLine("Done Iterating over existing usb devices: " + usbEventWatcher.UsbDeviceList.Count());

I cant figure out what i am missing....any ideas?

Thanks

Add sd-device backend for Linux

While libudev is not currently in danger of being abandoned yet as far as I can tell, the documentation suggests that it has been superseded by sd-device. Perhaps adding an sd-device backend alongside the libudev one should be investigated.

Not all USB based TTY (serial) devices enumerate or fire arrival/removal events

I have a C# application that utilizes udev to enumerate and receive events from USB based TTY (serial) devices and receive arrival/removal events. Your solution covers Windows/Mac/Linux and it is well implemented. However, it does not enumerate nor fire events for all the USB based TTY devices I use on my Linux system, devices with ttyACM* and ttyUSB*. I found that I have to filter on "tty" subsystem to enumerate/receive events for these devices.

Disposing UsbEventWatcher on Linux throws a null reference exception.

Library version
1.1.1.1

OS & OS version
Ubuntu Server 20.04 LTS

Describe the bug
When disposing UsbEventWatcher on Linux we get a null reference exception.

System.NullReferenceException : Object reference not set to an instance of an object. at Usb.Events.UsbEventWatcher.Dispose()

To Reproduce
Steps to reproduce the behavior:

  1. Create a disposable class with the UsbEventWatcher in it and dispose it (see code below)

(We used Dependency Injection when we found it, but it's easily reproducible by just calling the dispose method)

internal class Dummy : IDisposable
{
    private readonly UsbEventWatcher _usbEventWatcher = new();
    private bool _disposedValue;

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                _usbEventWatcher.Dispose();
            }

            _disposedValue = true;
        }
    }
}

Expected behavior
The Dispose method should not throw any null reference exceptions.

Additional context
I think it's the Windows specific objects _volumeChangeEventWatcher, _USBControllerDeviceCreationEventWatcher, _USBControllerDeviceDeletionEventWatcher that throws the exception as they are not created on the other platforms.
A simple null check per object or a Windows specific dispose section should fix it.

I do have one concern about this - are there any Linux/Mac specific objects that also needs to be disposed here?

USB exact description need to include.

Actually most of the device doesn't have any product name or vendor name. but still, vendors added some information inside the "Bus reported device description"

Some of the devices only included the vendor and product information, but in most of the cases these values will be default ones like the product: "USB Input Device", vendor: "Standard System device".

Solution recommended

If possible we can include the "Bus reported device description" into the below query.

 using ManagementObjectSearcher Win32_PnPEntity = new ManagementObjectSearcher($"SELECT Caption, ClassGuid, Description, DeviceID, Manufacturer FROM Win32_PnPEntity WHERE DeviceID LIKE '%{serial}%'");

This is the right method to identify the name for the devices most of the other keys are default ones so we are unable to find the exact devices.

This "Bus reported device description" can be set by the USB device, for instance

Some references.

public static DEVPROPKEY DEVPKEY_Device_BusReportedDeviceDesc = new DEVPROPKEY() { Fmtid = new Guid(0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2), Pid = 4 };
 usbDevice.BusReportedDeviceDescription = usbDevice.GetPropertyValue(UsbDeviceWinApi.DevicePropertyKeys.DEVPKEY_Device_BusReportedDeviceDesc) as String;

Issue with USB 3.0 drives?

Describe the bug
I have a problem with some USB devices. Normally I get the UsbDriveMounted and UsbDeviceAdded messages within seconds. However, for 2 devices, minutes pass between messages, plus the mounted directory path parameter is then empty.

The problematic devices are USB 3.0 devices, the others are older. The devices otherwise work flawlessly and immediately (Explorer)

Normal:
03.02.2021 12:36:14 UsbDriveMounted on: F:
03.02.2021 12:36:15 UsbDeviceAdded :
Device Name: F:
Device System Path: USB\VID_090C&PID_1000\16092007001318
Mounted Directory Path: F:
Product:
Product Description:
Product ID: 1000
Serial Number: 16092007001318
Vendor:
Vendor Description:
Vendor ID: 090C

Issue:
03.02.2021 12:36:25 UsbDriveMounted on: F:
03.02.2021 12:37:44 UsbDeviceAdded :
Device Name: USB-Massenspeichergerät
Device System Path: USB\VID_0781&PID_5591\0501DEDE8246E24347D1649F1F10436EBCAE8C977488E0B66FCFF5118298B533E94800000000000000000000CCFA9DFCFF0C041091558107A4A81936
Mounted Directory Path:
Product: USB-Massenspeichergerät
Product Description: USB-Massenspeichergerät
Product ID: 5591
Serial Number: 0501DEDE8246E24347D1649F1F10436EBCAE8C977488E0B66FCFF5118298B533E94800000000000000000000CCFA9DFCFF0C041091558107A4A81936
Vendor: Kompatibles USB-Speichergerät
Vendor Description: Kompatibles USB-Speichergerät
Vendor ID: 0781

How are you building and packing

Hi @Jinjinov - nice job on the library!

Are you building on each native system, copying the resulting binary and then packing on window?

I'm thinking of the flow as

dotnet build on linux and output binary as artifact
dotnet build on mac and output binary as artifact
copy binary artifacts from each agent to windows agent
dotnet pack on windows

More curious than anything - thanks in advance!

Application terminates immediately when USB is put in on MacOS

Library version

11.0.1.0 (latest)

OS, version, architecture (32 bit / 64 bit)

MacOS Ventura 13.5.1 on Apple M1 Pro chip (64 bit)

Describe the bug

The moment I insert a USB the program terminates, even though I don't see any code that does that. (there's no exceptions)
Just to be clear I am a massive beginner at C#, so if this is a problem on my end, I'm sorry in advance.

To Reproduce

Steps to reproduce the behavior:

  1. I downloaded the latest release
  2. I compiled the Program.cs in USB.Events.Test (inside the source code) using Visual Studio for Mac
  3. Run the program
  4. The moment I insert a USB the program terminates, even though I don't see any code that does that. (there's no exceptions)

Expected behaviour

Program doesn't stop and continues to report USB events

Include osx-arm64 target runtime

Thanks for a handy library.

On an M1 mac I get behavior like #32. I'm referencing the NuGet package. I get no notifications, no devices listed.

I noticed 11.0.1 does not include the osx-arm64 runtime. Could that be why?

PS C:\Users\doug\.nuget\packages\usb.events\11.0.1\runtimes> ls

    Directory: C:\Users\doug\.nuget\packages\usb.events\11.0.1\runtimes

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          11/15/2023    21:17                linux-arm
d----          11/15/2023    21:17                linux-arm64
d----          11/15/2023    21:17                linux-x64
d----          11/15/2023    21:17                linux-x86
d----          11/15/2023    21:17                osx-x64

Add TTY subsystem for Linux udev.

ttyACM and ttyUSB reside under the "tty" subsystem on Linux and are not currently discoverable via Usb.Events since it sets the subsystem to "usb".

When using a KVM switch (keyboard, video, mouse) the Added event is not fired, but the Remove event works

Library version
1.1.1.1

OS & OS version
Windows 10 Pro (19042.985)

Describe the bug
I connect/disconect some USB devices, and it only registers events when I remove it but not when I connect it to the PC.

To Reproduce
Steps to reproduce the behavior:
I'm just importing the library via nuget and running the sample source code from the readme.md. And then plug/unplug some USB devices.

Expected behavior
See DeviceAdded events

After instantiating the class, the list of enumerated devices is empty

When devices are enumerated in the UsbEventWatcher.Linux.c file, EnumerateDevices() calls ProcessDevice() which calls GetDeviceInfo() which expects action to be set to either "add" or "remove" in order to call the appropriate callback function to either add or remove a device from the list kept in the C# class. However, no action is set when enumerating on when a hot plug event occurs, so the list will not be popluated.

Capture device number and bus number on Linux

Is your feature request related to a problem? Please describe.
I would like to have access to the Linux system attributes Device Num and Bus Num for usb devices.

Describe the solution you'd like
Would you be able to add calls in UsbEventWatcher.Linux.c GetDeviceInfo():
udev_device_get_sysattr_value(dev, "devnum")
udev_device_get_sysattr_value(dev, "busnum")

And add 2 new fields into the common UsbDevice class. I am not sure if these fields make sense on Windows and Mac also, they may not be available. In which case can just put a disclaimer in the comments

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.