a1ien / rusb

A safe Rust wrapper for libusb.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Receiving notifications despite a filter

joelreymont opened this issue · comments

I set up a vid/pid filter expecting ctx.handle_events not to return unless a notification for my device of choice is received.

I receive connect/disconnect notifications for any device that's attached or detached, though.

Is there a bug in the code or am I supposed to manually figure out if my device was attached or detached, like I'm doing below?

In other words, how do I wait for my device to appear or disappear without polling for it?

   if rusb::has_hotplug() {
        let ctx = Context::new()?;

        let mut reg = Some(
            HotplugBuilder::new()
                .enumerate(true)
                .vendor_id(args.vid)
                .product_id(args.pid)
                .register(&ctx, Box::new(HotPlugHandler {}))?,
        );

        loop {
            ctx.handle_events(None).unwrap();
            if is_connected(ctx.devices(), args.vid, args.pid) {
                if let Some(reg) = reg.take() {
                    ctx.unregister_callback(reg);
                    break;
                }
            }
        }

I can't reproduce you problem. What linux distro do you use?

use rusb::{Context, Device, HotplugBuilder, UsbContext};

struct HotPlugHandler;

impl<T: UsbContext> rusb::Hotplug<T> for HotPlugHandler {
    fn device_arrived(&mut self, device: Device<T>) {
        println!("device arrived {:?}", device);
    }

    fn device_left(&mut self, device: Device<T>) {
        println!("device left {:?}", device);
    }
}

impl Drop for HotPlugHandler {
    fn drop(&mut self) {
        println!("HotPlugHandler dropped");
    }
}

fn main() -> rusb::Result<()> {
    if rusb::has_hotplug() {
        let context = Context::new()?;

        let mut reg: Option<rusb::Registration<Context>> = Some(
            HotplugBuilder::new()
                .enumerate(true)
                .vendor_id(0x18d1)
                .product_id(0x4ee7)
                .register(&context, Box::new(HotPlugHandler {}))?,
        );

        loop {
            context.handle_events(None).unwrap();
        }
        Ok(())
    } else {
        eprint!("libusb hotplug api unsupported");
        Ok(())
    }
}

I tested this on MacOS Venture (13.0.1) as well as Ubuntu 22.10.

Please change the code in the loop to look like this and you may see what I'm complaining about:

               context.handle_events(None).unwrap();
                if let Some(reg) = reg.take() {
                    ctx.unregister_callback(reg);
                    break;
                }

You should see context.handle_events returning for any device inserted or removed, not just the ones you are filtering for. If that's correct behavior then how do I wait for my device events without polling?

There are operations that should not be performed in the callbacks and it would be natural to wait for a device in the loop and then perform any necessary operations once the device was attached or detached.

This is expected behavioral. handle_events just handle any events. You should run it in separate thread.
If you wand get you device look at this example #100 (comment)