Discussion:
[Libusb-devel] HID Report Descriptor
Alan Ott
2011-01-15 07:02:32 UTC
Permalink
Hi,

I'm trying to read the HID report descriptor for a device. Really, I'm
just trying to get the Usage Page and Usage out of the HID report
descriptor. Best I've been able to tell, this is done using a
libusb_control_transfer() [1].

The problem is, to do this type of control transfer (one that contains
LIBUSB_RECIPIENT_INTERFACE), you have to call libusb_claim_interface()
first. In order to call libusb_claim_interface(), you have to call
libusb_detach_kernel_driver().

The code[1] works. But what happens is that every time someone calls my
hid_enumerate() function, the kernel driver for every HID device gets
detached and re-attached (because I have to detach and re-attach to get
the HID report descriptor). This seems less than desirable. Further, the
detach and re-attach sequence will re-shuffle the device numbers for the
kernel device files for these devices in some cases. (For example,
hidraw1 and hidraw2 will become hidraw0 and hidraw1 in some cases).

Clearly my hid_enumerate() function should be as less invasive as
possible. The detach/claim/release/attach sequence seems invasive. Is
there a better way that I'm missing?

Alan.

[1] https://github.com/signal11/hidapi/blob/master/linux/hid-libusb.c#L469
Ludovic Rousseau
2011-01-15 09:28:05 UTC
Permalink
Post by Alan Ott
Hi,
Hello,
Post by Alan Ott
I'm trying to read the HID report descriptor for a device. Really, I'm
just trying to get the Usage Page and Usage out of the HID report
descriptor. Best I've been able to tell, this is done using a
libusb_control_transfer() [1].
The problem is, to do this type of control transfer (one that contains
LIBUSB_RECIPIENT_INTERFACE), you have to call libusb_claim_interface()
first. In order to call libusb_claim_interface(), you have to call
libusb_detach_kernel_driver().
The code[1] works. But what happens is that every time someone calls my
hid_enumerate() function, the kernel driver for every HID device gets
detached and re-attached (because I have to detach and re-attach to get
the HID report descriptor). This seems less than desirable. Further, the
detach and re-attach sequence will re-shuffle the device numbers for the
kernel device files for these devices in some cases. (For example,
hidraw1 and hidraw2 will become hidraw0 and hidraw1 in some cases).
Clearly my hid_enumerate() function should be as less invasive as
possible. The detach/claim/release/attach sequence seems invasive. Is
there a better way that I'm missing?
libusb_detach_kernel_driver() also has other bad side effects. See my
thread "libusb_detach_kernel_driver() also has the side effect of
libusb_release_interface()" [2].

For this reason I removed the call to libusb_detach_kernel_driver() in
my version of hidapi and I use a udev script [3] to detach the HID
kernel driver when the USB device is connected (and only when the
device is connected).

I think that using libusb_detach_kernel_driver() in hidapi is too dangerous.

Bye
Post by Alan Ott
[1] https://github.com/signal11/hidapi/blob/master/linux/hid-libusb.c#L469
[2] http://libusb.6.n5.nabble.com/libusb-detach-kernel-driver-also-has-the-side-effect-of-libusb-release-interface-td3267040.html
[3] http://libusb.6.n5.nabble.com/Automatic-detach-of-a-HID-device-using-udev-Re-How-to-dump-HID-report-descriptor-under-Linux-tp3330260p3334978.html
--
 Dr. Ludovic Rousseau
Alan Ott
2011-01-15 16:00:48 UTC
Permalink
Post by Ludovic Rousseau
libusb_detach_kernel_driver() also has other bad side effects. See my
thread "libusb_detach_kernel_driver() also has the side effect of
libusb_release_interface()" [2].
For this reason I removed the call to libusb_detach_kernel_driver() in
my version of hidapi and I use a udev script [3] to detach the HID
kernel driver when the USB device is connected (and only when the
device is connected).
In reference to [2], does calling libusb_kernel_driver_active() and
using it to determine if the kernel driver is attached before calling
libusb_detach_kernel_driver() solve your problem?
Post by Ludovic Rousseau
[2] http://libusb.6.n5.nabble.com/libusb-detach-kernel-driver-also-has-the-side-effect-of-libusb-release-interface-td3267040.html
[3] http://libusb.6.n5.nabble.com/Automatic-detach-of-a-HID-device-using-udev-Re-How-to-dump-HID-report-descriptor-under-Linux-tp3330260p3334978.html
Ludovic Rousseau
2011-01-17 09:10:02 UTC
Permalink
Post by Ludovic Rousseau
libusb_detach_kernel_driver() also has other bad side effects. See my
thread "libusb_detach_kernel_driver() also has the side effect of
libusb_release_interface()" [2].
For this reason I removed the call to libusb_detach_kernel_driver() in
my version of hidapi and I use a udev script [3] to detach the HID
kernel driver when the USB device is connected (and only when the
device is connected).
In reference to [2], does calling libusb_kernel_driver_active() and using it
to determine if the kernel driver is attached before calling
libusb_detach_kernel_driver() solve your problem?
Yes. Using libusb_kernel_driver_active() does solve my problem and my
udev rule file is now much more simple. I just need to set the access
rights.
You can use/merge my patch from github [4].

The problem with hidapi now is that libusb_detach_kernel_driver() is
called for every HID device in hid_enumerate(). And, as you know, that
has unwanted side effects.
I propose to get the HID Report Descriptor in hid_open() instead of
hid_enumerate().

Bye
Post by Ludovic Rousseau
[2]
http://libusb.6.n5.nabble.com/libusb-detach-kernel-driver-also-has-the-side-effect-of-libusb-release-interface-td3267040.html
[3]
http://libusb.6.n5.nabble.com/Automatic-detach-of-a-HID-device-using-udev-Re-How-to-dump-HID-report-descriptor-under-Linux-tp3330260p3334978.html
[4] https://github.com/LudovicRousseau/hidapi/commit/2a172eeef0ba36b92bc9b1436a1c0166743e19a8
--
 Dr. Ludovic Rousseau
Alan Ott
2011-01-17 14:44:52 UTC
Permalink
Post by Ludovic Rousseau
Yes. Using libusb_kernel_driver_active() does solve my problem and my
udev rule file is now much more simple. I just need to set the access
rights.
You can use/merge my patch from github [4].
Excellent.
Post by Ludovic Rousseau
The problem with hidapi now is that libusb_detach_kernel_driver() is
called for every HID device in hid_enumerate(). And, as you know, that
has unwanted side effects.
Yes, I'm going to pull that out. It's not good.
Post by Ludovic Rousseau
I propose to get the HID Report Descriptor in hid_open() instead of
hid_enumerate().
Well, the idea was that a person could decide which device they were
going to open using the Usage and Usage Page (before they open it).
There's API for this on Windows and Mac. This is useful for composite
devices (a device with multiple interfaces, each of them HID).

I think what I'm going to have to do here is put Usage and Usage Page in
the hid_device_info struct on Windows and Mac only, and put the
Interface number in the struct on Linux/libusb.

I don't like it, but I can't be doing this detach thing, and there needs
to be some way to differentiate interfaces on Linux. And of course,
getting the Interface number on Windows or Mac using the platform HID
libraries isn't possible (at least I haven't seen it, but I'll look again).

Alan.
Post by Ludovic Rousseau
[4] https://github.com/LudovicRousseau/hidapi/commit/2a172eeef0ba36b92bc9b1436a1c0166743e19a8
Peter Stuge
2011-01-17 16:47:28 UTC
Permalink
Post by Alan Ott
I think what I'm going to have to do here is put Usage and Usage Page in
the hid_device_info struct on Windows and Mac only, and put the
Interface number in the struct on Linux/libusb.
I don't like it, but I can't be doing this detach thing, and there needs
to be some way to differentiate interfaces on Linux.
Maybe libudev or libsysfs can be helpful.


//Peter
Alan Ott
2011-01-20 23:38:03 UTC
Permalink
Post by Peter Stuge
Post by Alan Ott
I think what I'm going to have to do here is put Usage and Usage Page in
the hid_device_info struct on Windows and Mac only, and put the
Interface number in the struct on Linux/libusb.
I don't like it, but I can't be doing this detach thing, and there needs
to be some way to differentiate interfaces on Linux.
Maybe libudev or libsysfs can be helpful.
Hi Peter,

I've checked sysfs, and report descriptors are unfortunately not
exported as a sysfs entry. Libudev of course just reads sysfs entries.
Maybe I could add that to the kernel.

Alan.
Alan Ott
2011-01-21 06:25:24 UTC
Permalink
Post by Alan Ott
Post by Peter Stuge
Maybe libudev or libsysfs can be helpful.
I've checked sysfs, and report descriptors are unfortunately not
exported as a sysfs entry. Libudev of course just reads sysfs entries.
Maybe I could add that to the kernel.
Preliminary patch to the kernel for this feature:
https://lkml.org/lkml/2011/1/21/13
Alan Stern
2011-01-21 15:20:39 UTC
Permalink
Post by Alan Ott
Post by Alan Ott
Post by Peter Stuge
Maybe libudev or libsysfs can be helpful.
I've checked sysfs, and report descriptors are unfortunately not
exported as a sysfs entry. Libudev of course just reads sysfs entries.
Maybe I could add that to the kernel.
https://lkml.org/lkml/2011/1/21/13
It would make more sense to export the report descriptors as binary
blobs (rather than ASCII hex dumps), since that what they are. And
that's what programs expect to read.

Alan Stern
Alan Ott
2011-01-21 15:28:03 UTC
Permalink
Post by Alan Stern
Post by Alan Ott
Post by Alan Ott
Post by Peter Stuge
Maybe libudev or libsysfs can be helpful.
I've checked sysfs, and report descriptors are unfortunately not
exported as a sysfs entry. Libudev of course just reads sysfs entries.
Maybe I could add that to the kernel.
https://lkml.org/lkml/2011/1/21/13
It would make more sense to export the report descriptors as binary
blobs (rather than ASCII hex dumps), since that what they are. And
that's what programs expect to read.
I agree. However, I thought there was a policy regarding sysfs about
data being plain text? I thought I read that on LWN at one point. Maybe
I'm wrong.
Alan Stern
2011-01-21 15:39:15 UTC
Permalink
Post by Alan Ott
Post by Alan Stern
It would make more sense to export the report descriptors as binary
blobs (rather than ASCII hex dumps), since that what they are. And
that's what programs expect to read.
I agree. However, I thought there was a policy regarding sysfs about
data being plain text? I thought I read that on LWN at one point. Maybe
I'm wrong.
Yes, you're wrong. See the usage of bin_attribute in fs/sysfs/bin.c.
For an example of a binary attribute, see the dev_bin_attr_descriptors
stuff in drivers/usb/core/sysfs.c.

Alan Stern
Greg KH
2011-01-21 19:17:51 UTC
Permalink
Post by Alan Stern
Post by Alan Ott
Post by Alan Stern
It would make more sense to export the report descriptors as binary
blobs (rather than ASCII hex dumps), since that what they are. And
that's what programs expect to read.
I agree. However, I thought there was a policy regarding sysfs about
data being plain text? I thought I read that on LWN at one point. Maybe
I'm wrong.
Yes, you're wrong. See the usage of bin_attribute in fs/sysfs/bin.c.
For an example of a binary attribute, see the dev_bin_attr_descriptors
stuff in drivers/usb/core/sysfs.c.
To be a bit more clear, binary attributes in sysfs are allowed, as long
as the kernel is only a "conduit" to the data, and it does not intrepret
it or modify it in any way. For example, "raw" USB descriptor data, PCI
descriptor data, firmware files, etc, are all binary sysfs files. HID
descriptor files would also be fine in sysfs as binary if the kernel
isn't trying to modify them in any manner.

thanks,

greg k-h

Loading...