ryankurte / rust-streamdeck

libusb based driver for Elgato StreamDeck devices
Mozilla Public License 2.0
57 stars 24 forks source link

Can't connect to Streamdeck #6

Closed markmandel closed 4 years ago

markmandel commented 4 years ago

Not sure what I'm doing wrong. Hopefully if we can resolve this, it could be turned into a nice example.

I'm using HidApi to search for my Streamdeck, and then connecting to it from there.

My code looks like the following:

    let hid = HidApi::new().expect("could not connect to hidapi");
    let device = hid
        .device_list()
        .filter(|item| item.product_id() == XL)
        .next()
        .expect("Could not find Streamdeck");

    println!(
        "Attempting to connect to {:?}. vid: {:?}, pid: {:?}, serial: {:?}",
        device.product_string(),
        device.vendor_id(),
        device.product_id(),
        device.serial_number(),
    );

    let mut deck = StreamDeck::connect(device.vendor_id(), device.product_id(), None)
        .expect("could not connect to StreamDeck");

But whenever I run it I get back:

➜  streamdeck-agent git:(master) ✗ RUST_BACKTRACE=full cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.06s
     Running `target/debug/streamdeck-agent`
Attempting to connect to Some("Stream Deck XL"). vid: 4057, pid: 108, serial: Some("CLXXXXXXX")
thread 'main' panicked at 'could not connect to StreamDeck: Hid(InitializationError)', src/main.rs:26:20
stack backtrace:
   0:     0x55822ad72444 - backtrace::backtrace::libunwind::trace::h90669f559fb267f0
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1:     0x55822ad72444 - backtrace::backtrace::trace_unsynchronized::hffde4e353d8f2f9a
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2:     0x55822ad72444 - std::sys_common::backtrace::_print_fmt::heaf44068b7eaaa6a
                               at src/libstd/sys_common/backtrace.rs:77
   3:     0x55822ad72444 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h88671019cf081de2
                               at src/libstd/sys_common/backtrace.rs:59
   4:     0x55822ad8a74c - core::fmt::write::h4e6a29ee6319c9fd
                               at src/libcore/fmt/mod.rs:1052
   5:     0x55822ad70667 - std::io::Write::write_fmt::hf06b1c86d898d7d6
                               at src/libstd/io/mod.rs:1426
   6:     0x55822ad745d5 - std::sys_common::backtrace::_print::h404ff5f2b50cae09
                               at src/libstd/sys_common/backtrace.rs:62
   7:     0x55822ad745d5 - std::sys_common::backtrace::print::hcc4377f1f882322e
                               at src/libstd/sys_common/backtrace.rs:49
   8:     0x55822ad745d5 - std::panicking::default_hook::{{closure}}::hc172eff6f35b7f39
                               at src/libstd/panicking.rs:204
   9:     0x55822ad742c1 - std::panicking::default_hook::h7a68887d113f8029
                               at src/libstd/panicking.rs:224
  10:     0x55822ad74c3a - std::panicking::rust_panic_with_hook::hb7ad5693188bdb00
                               at src/libstd/panicking.rs:472
  11:     0x55822ad74820 - rust_begin_unwind
                               at src/libstd/panicking.rs:380
  12:     0x55822ad89c11 - core::panicking::panic_fmt::hb1f3e14b86a3520c
                               at src/libcore/panicking.rs:85
  13:     0x55822ad89a33 - core::option::expect_none_failed::he6711468044f7162
                               at src/libcore/option.rs:1199
  14:     0x55822acfc4a8 - core::result::Result<T,E>::expect::h42b271c894e69dc2
                               at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/result.rs:991
  15:     0x55822acfd2c1 - streamdeck_agent::main::hfc6bf6dfee7fcc46
                               at src/main.rs:26
  16:     0x55822acfdf50 - std::rt::lang_start::{{closure}}::hc3f82a756dc7500e
                               at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/rt.rs:67
  17:     0x55822ad74703 - std::rt::lang_start_internal::{{closure}}::hb26e39676675046f
                               at src/libstd/rt.rs:52
  18:     0x55822ad74703 - std::panicking::try::do_call::he4701ab6e48d80c0
                               at src/libstd/panicking.rs:305
  19:     0x55822ad77067 - __rust_maybe_catch_panic
                               at src/libpanic_unwind/lib.rs:86
  20:     0x55822ad750e0 - std::panicking::try::hd3de25f3cb7024b8
                               at src/libstd/panicking.rs:281
  21:     0x55822ad750e0 - std::panic::catch_unwind::h86c02743a24e3d92
                               at src/libstd/panic.rs:394
  22:     0x55822ad750e0 - std::rt::lang_start_internal::h9cf8802361ad86c2
                               at src/libstd/rt.rs:51
  23:     0x55822acfdf29 - std::rt::lang_start::h69c7f105ba132008
                               at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/rt.rs:67
  24:     0x55822acfd83a - main
  25:     0x7f4889441e0b - __libc_start_main
  26:     0x55822acfb40a - _start
  27:                0x0 - <unknown>

I've tried this with passing the Serial number through, and without. I'm at a bit of a loss :disappointed:

As an aside - I am able to connect via streamdeck-ui, with their udev rules, as well as your udev rules, so I don't think that is the issue.

ryankurte commented 4 years ago

Huh, interesting. Is there a reason you need to Open HidAPI yourself? We do this internally, and, I would not be surprised if this is the cause of the issue.

Passing the appropriate (constant) VID/PID for a streamdeck XL to the connect call should achieve the same function as your example, they are unique for a given type of product, and what we use internally to determine product type.

And if you do need the HidAPI instance externally we could add a connect_with_hidapi constructor that passes an existing instance in (and refactor the connect constructor to use this internally).

markmandel commented 4 years ago

Thanks for the quick reply! I think I was just starting to come to the same conclusion - that creating the HidAPI first was causing the issues.

I guess, as new person to trying to make this connection (and working with StreamDeck), I had no idea what the device values should be, or how to even look them up -- or even if they were even constant. So I went looking for a searching tool -- I don't explicitly need to library for any reason other than that.

Looking at my code, I see I could also create my own StreamDeck instance (basically mimic what you do in connect(), or maaaaybe drop my initial hid once I've worked out the details of what I want to connect to.

markmandel commented 4 years ago

Worked out a nice workaround! :+1: Shifted my discovery code into it's own function, and now everything works, since the discover instance of HidAPI gets dropped as soon as we move out of the scope of the find_deck function.

Works for me!

    let (vid, pid, serial) = find_deck();
    let mut deck = StreamDeck::connect(vid, pid, serial).expect("could not connect to StreamDeck");

    println!("Connected!");
fn find_deck() -> (u16, u16, Option<String>) {
    let hid = HidApi::new().expect("could not connect to hidapi");
    let device = hid
        .device_list()
        .filter(|item| item.product_id() == XL)
        .next()
        .expect("Could not find Streamdeck");

    println!(
        "Attempting to connect to {:?}. vid: {:?}, pid: {:?}, serial: {:?}",
        device.product_string(),
        device.vendor_id(),
        device.product_id(),
        device.serial_number(),
    );

    (
        device.vendor_id(),
        device.product_id(),
        device.serial_number().map(|str| String::from(str)),
    )
}
ryankurte commented 4 years ago

Yeah, we could certainly add the elgato VID and device PIDs to the readme or docs to make this clearer. Glad you’ve found a solution.