1

Topic: Create an event when attach/detach removable drive HidSharp Linux

Hi all!
I try to use nuget package HidSharp 2.0.5 for catch an event when removable drive is connected/disconnected. I'm debugging on Windows now, but my code is does not catch any hid devices connection events. I would be run this app at Linux in future via Mono. Can anyone help me please?

static void Main(string[] args)
    {
        var list = DeviceList.Local;

        Console.WriteLine("USB monitor");

        list.Changed += (sender, e) => Console.WriteLine("Device list changed.");

        var hidDeviceList = list.GetHidDevices().ToArray();

        Console.WriteLine("Complete device list {0} devices:", hidDeviceList.Length);

        foreach (var device in hidDeviceList)
        {
            Console.WriteLine(device);
        }

        Console.ReadLine();
    }

2

Re: Create an event when attach/detach removable drive HidSharp Linux

Hmm. Is the removable drive also a USB HID device? If not, you'd probably want to use the udev API or similar. (Internally, HidSharp uses udev, but only to listen for HID device changes.)

3 (edited by Jman 2018-12-18 07:16:32)

Re: Create an event when attach/detach removable drive HidSharp Linux

Thank you for your reply! I think it's not a HID device, just regular removable drive. I think I need somethink like this:

protected override void Run(Action readyCallback)
ret = NativeMethodsLibudev.Instance.udev_monitor_filter_add_match_subsystem_devtype(monitor, "hidraw", null);

Am I right?
So, then I should try to add action from udev:

var device = udev_monitor_receive_device(monitor);
                try {
                    var action = udev_device_get_action(device);
                    var syspath = udev_device_get_syspath(device);
                    switch (action) {
                    case "add":
                        if (syspath != null) {
                            paths.Add(syspath);
                        }
                        break;
                    case "remove":
                        paths.Remove(syspath);
                        break;
                    }

But I dont know, how to throw action result to main program.

PS: In my case  events in my first post does not work with any HID devices on Win10.
PSS:
I try:

class LinuxHidManager 
    {
        IntPtr udev;
        IntPtr monitor;
        IList<string> paths = new SynchronizedCollection<string>(); // System.ServiceModel

        public void Init()
        {
            // TODO: should probably do some better error checking here
            udev = udev_new();

            Console.WriteLine("Path udev = udev_new();");

            monitor = udev_monitor_new_from_netlink(udev, "udev");
            udev_monitor_filter_add_match_subsystem_devtype(monitor, "hidraw", null);
            udev_monitor_enable_receiving(monitor);
            var enumerate = udev_enumerate_new(udev);
            try
            {
                udev_enumerate_add_match_subsystem(enumerate, "hidraw");
                udev_enumerate_scan_devices(enumerate);
                for (var entry = udev_enumerate_get_list_entry(enumerate);
                     entry != IntPtr.Zero;
                     entry = udev_list_entry_get_next(entry))
                {
                    var syspath = udev_list_entry_get_name(entry);
                    if (syspath != null)
                    {
                        paths.Add(syspath);
                    }
                }

                Console.WriteLine("Path udev_enumerate_add_match_subsystem");
            }
            finally
            {
                udev_enumerate_unref(enumerate);
            }
            // FIXME: Need to implement IDisposeable and free udev and monitor
        }

        public string Runing()
        {
            Console.WriteLine("Entered in Runing()");

            string action;
            var fds = new pollfd[1];
            fds[0].fd = udev_monitor_get_fd(monitor);
            fds[0].events = pollev.IN;
            Console.WriteLine("Pass fds[0].events = pollev.IN;");
            while (true)
            {
                int ret = retry(() => poll(fds, (IntPtr)fds.Length, -1)); // What happened here??? Program will freeze!!!
                Console.WriteLine("Pass в retry(() => poll;");
                if (ret == -1)
                {
                    Console.WriteLine("Something went wrong");
                    // FIXME: how do we notify the main program that something bad happened here?
                    break;
                }
                var device = udev_monitor_receive_device(monitor);
                try
                {
                    Console.WriteLine("Catch an action");
                    action = udev_device_get_action(device);
                    var syspath = udev_device_get_syspath(device);
                    Console.WriteLine(syspath);
                    switch (action)
                    {
                        case "add":
                            if (syspath != null)
                            {
                                paths.Add(syspath);
                            }
                            break;
                        case "remove":
                            paths.Remove(syspath);
                            break;
                    }
                    Console.WriteLine("What message in action");
                    

                    return action;
                }
                finally
                {
                    udev_device_unref(device);
                }
            }

            return "Test";
        }

        protected object[] Refresh()
        {
            return paths.Cast<object>().ToArray();
        }

        public bool IsSupported
        {
            get
            {
                // basically, we are just testing if libudev is present
                try
                {
                    var udev = NativeMethods.udev_new();
                    if (udev == IntPtr.Zero)
                    {
                        return false;
                    }
                    NativeMethods.udev_unref(udev);
                    return true;
                }
                catch (DllNotFoundException)
                {
                    return false;
                }
            }
        }
    }
    
    
  // ++++++++++++++++++++++++ MAIN (TEST) ++++++++++++++++++++++++ 
  class Program
    {
        static LinuxHidManager ld = new LinuxHidManager();
        private static string Message { get; set; }

        static void Main(string[] args)
        {
            
            Console.WriteLine("++++++++++++++++++++++++++++");
            Init();
            Console.ReadLine();
        }

        private static void Init()
        {
            ld.Init();
            Message = ld.Runing();

I use only NativeMethods and LinuxHidManger classes for test. And I want to get action messages from udev... I've added Console.WriteLine for debugging line by line...