ruabmbua / hidapi-rs

Rust bindings for the hidapi C library
MIT License
172 stars 81 forks source link

Can't create a HidApi instance on Windows 7 #52

Closed fpagliughi closed 4 years ago

fpagliughi commented 4 years ago

Hi. I'm trying to build and run the example apps on Windows 7, and am getting an error when it tries to calls HidApi::new():

./target/debug/examples/lshid.exe
Printing all available hid devices:
Error: failed converting 0xDDCD to rust char

./target/debug/examples/lshid.exe
Printing all available hid devices:
Error: failed converting 0xDEE7 to rust char

Any ideas?

I'm using the latest Rust 1.41.1 with hidapi v 1.1.1

ruabmbua commented 4 years ago

You probably have a device attached, which contains some invalid UTF-16 in e.g. the serial number, product name etc...

You can handle the HidError::FromWideCharError for your case.

ruabmbua commented 4 years ago

Update: I think it is impossible currently to enumerate devices, when one contains some invalid UTF-16...

Did not expect that one. I think I can come up with a fix. Should not take long. Are you willing to test, if it fixes your problem?

lnicola commented 4 years ago

I wonder if the device actually returns an invalid string, or something along the way (Windows) messes it up.

fpagliughi commented 4 years ago

Yes. Interesting. I hit a bug in the rusb crate with this same machine a few days ago: https://github.com/a1ien/rusb/issues/15

It seemed that a device was returning at least one bad descriptor claiming a length of 255 bytes and very suspect contents. In that case the fix that I submitted did a basic check and didn't even try to parse the string in that case. For example... if it returns a string with an odd number length, then that is definitely wrong. Don't even try to parse it. Return an error.

fpagliughi commented 4 years ago

Sorry I needed to step away from the computer for a short while. I will be back in a few minutes to test the update and report back.

fpagliughi commented 4 years ago

Well it doesn't crash anymore, which is good, but now I'm seeing this:

lshid.exe
Printing all available hid devices:
VID: 046a, PID: 010d, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>
VID: 046a, PID: 010d, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>
VID: 046d, PID: c52f, Serial: <COULD NOT FETCH>, Product name: ∁CԇंĄĀ
VID: 046d, PID: c52f, Serial: <COULD NOT FETCH>, Product name: ࠀ
VID: 046d, PID: c52f, Serial: ᄡ∁CԇंĄĀ, Product name: <COULD NOT FETCH>
VID: 046d, PID: c52f, Serial: ǩࠀ, Product name: <COULD NOT FETCH>

From the VID's, that's my Cherry keyboard and Logitech wireless mouse. They're connected through a TESmart KVM. I wonder if the KVM is scrambling the USB descriptors.

ruabmbua commented 4 years ago

Wow.

I guess windows really fucks this one up. I guess the weird symbols are valid unicode, but you do not have the font.

ruabmbua commented 4 years ago

Would not be surprised if it reads random data. Does windows have something like address sanitizer working?

lnicola commented 4 years ago

I do have the fonts, and those strings are junk, including one PUA character :laughing:.

Do the devices show up fine when running the code on Linux? What about a different Windows version (although I suppose that's a hassle to install)?

lnicola commented 4 years ago

@ruabmbua MSDN doesn't specify it, but I think the strings are UTF-16. wchar_t is u16 on Windows, at least. By taking one wchar_t at a time and converting it to a char, you might be getting the wrong data.

lnicola commented 4 years ago

@fpagliughi Can you change the example to use serial_number_raw, respectively manufacturer_string_raw, then debug-print them?

The way the new API works, only one of serial_number and serial_number_raw will work. I'm interested in what you get from the _raw methods when their pair returns <COULD NOT FETCH>.

ruabmbua commented 4 years ago

@fpagliughi Yeah, please try that. If it works I may have to fix the non raw version.

lnicola commented 4 years ago

I didn't expect it, but somehow the string conversion works fine for me on Windows:

Printing all available hid devices:
VID: 04f3, PID: 0401, Serial: 9999, Product name: HIDI2C Device
VID: 04f3, PID: 0401, Serial: 9999, Product name: HIDI2C Device
VID: 004c, PID: 0269, Serial: 186590ca7777, Product name: Magic Mouse 2
VID: 004c, PID: 0269, Serial: 186590ca7777, Product name: Magic Mouse 2
VID: 0000, PID: 0000, Serial: <COULD NOT FETCH>: None, Product name: <COULD NOT FETCH>: None
VID: 04d9, PID: a052, Serial: 1.40, Product name: USB-zyTemp
diff --git a/examples/lshid.rs b/examples/lshid.rs
index 89237f2..9a5ca60 100644
--- a/examples/lshid.rs
+++ b/examples/lshid.rs
@@ -21,12 +21,12 @@ fn main() {
                     device.vendor_id(),
                     device.product_id(),
                     match device.serial_number() {
-                        Some(s) => s,
-                        _ => "<COULD NOT FETCH>",
+                        Some(s) => s.to_string(),
+                        _ => format!("<COULD NOT FETCH>: {:?}", device.serial_number_raw()),
                     },
                     match device.product_string() {
-                        Some(s) => s,
-                        _ => "<COULD NOT FETCH>",
+                        Some(s) => s.to_string(),
+                        _ => format!("<COULD NOT FETCH>: {:?}", device.product_string_raw()),
                     }
                 );
             }
fpagliughi commented 4 years ago

Just as a comparison I switched the KVM over to a Linux box (Mint 19), so this would have the same keyboard and mouse as the Windows version. Comparing to the output of lsusb,

$ lsusb
Bus 002 Device 003: ID 0458:0007 KYE Systems Corp. (Mouse Systems) 
Bus 003 Device 005: ID 046d:c52f Logitech, Inc. Unifying Receiver
Bus 003 Device 004: ID 046a:010d Cherry GmbH 

$ ./target/debug/examples/lshid
Printing all available hid devices:
VID: 0458, PID: 0007, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>
VID: 046d, PID: c52f, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>
VID: 046d, PID: c52f, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>
VID: 046a, PID: 010d, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>
VID: 046a, PID: 010d, Serial: <COULD NOT FETCH>, Product name: <COULD NOT FETCH>

So it doesn't seem to be a Windows-only issue.

fpagliughi commented 4 years ago

Just to be clear, as I remember it, USB strings use fixed 16-bit encoding. The string descriptors are returned to the host with a 2-byte header followed by the 16-bit string characters.

The 1st byte of the descriptor contains the byte length of the descriptor, and the 2nd byte contains the descriptor type which should always be 0x03 for a string descriptor.

Given all that, when you read a string descriptor, you can/should make the following sanity checks:

fpagliughi commented 4 years ago

Ah, yeah, sorry. I've been deep into libusb/rusb all week. Forgot, the C hidapi gives you back the wchar_t* directly, not the descriptor.

So I just tried the to compile and build the test app from the C hidapi in Linux and it isn't giving me back the strings:

$ sudo ./hidtest/hidtest-libusb 
Device Found
  type: 0458 0007
  path: 0002:0003:00
  serial_number: (null)
  Manufacturer: HP
  Product:      HP USB WHEEL MOUSE
  Release:      0
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c52f
  path: 0003:0005:00
  serial_number: (null)
  Manufacturer: (null)
  Product:      (null)
  Release:      3000
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c52f
  path: 0003:0005:01
  serial_number: (null)
  Manufacturer: (null)
  Product:      (null)
  Release:      3000
  Interface:    1
  Usage (page): 0x0 (0x0)

Device Found
  type: 046a 010d
  path: 0003:0004:00
  serial_number: (null)
  Manufacturer: (null)
  Product:      (null)
  Release:      100
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046a 010d
  path: 0003:0004:01
  serial_number: (null)
  Manufacturer: (null)
  Product:      (null)
  Release:      100
  Interface:    1
  Usage (page): 0x0 (0x0)

unable to open device
ruabmbua commented 4 years ago

I will close this issue. Seems to be related to hidapi, or the specific setup.

fpagliughi commented 4 years ago

Yes. It seems like this is something that needs to be fixed upstream. I will need to figure it out over the next few weeks and will update if I find it.

ruabmbua commented 4 years ago

@fpagliughi Can you please update this thread if you find something?

I`d like to be aware of the issue, if I have some more time for implementing raw rust hidapi. Thanks!