Closed fpagliughi closed 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.
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?
I wonder if the device actually returns an invalid string, or something along the way (Windows) messes it up.
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.
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.
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.
Wow.
I guess windows really fucks this one up. I guess the weird symbols are valid unicode, but you do not have the font.
Would not be surprised if it reads random data. Does windows have something like address sanitizer working?
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)?
@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.
@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>
.
@fpagliughi Yeah, please try that. If it works I may have to fix the non raw version.
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()),
}
);
}
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.
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:
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
I will close this issue. Seems to be related to hidapi, or the specific setup.
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.
@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!
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()
:Any ideas?
I'm using the latest Rust 1.41.1 with hidapi v 1.1.1