Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid usage_page values in Linux #385

Open
tresf opened this issue Mar 21, 2018 · 12 comments
Open

Invalid usage_page values in Linux #385

tresf opened this issue Mar 21, 2018 · 12 comments

Comments

@tresf
Copy link

tresf commented Mar 21, 2018

I have a Honeywell 1400g barcode scanner which identifies itself as:

Vendor Product Serial
0x0c2e 0x0b87 17338B352C

It has two endpoints:

Endpoint 1 Endpoint 2
UsagePage -116 140

On Windows and MacOS, I can use UsagePage to distinguish between the two. We toss out the -116 and keep the 140 and we have the proper device and can read HID data from it.

Unfortunately, the two endpoints are causing trouble when claiming the device in Linux: both UsagePage values return zero.

The source of hid.c makes this appear intentional:

/* Uncomment to enable the retrieval of Usage and Usage Page in
hid_enumerate(). Warning, on platforms different from FreeBSD
this is very invasive as it requires the detach
and re-attach of the kernel driver. See comments inside hid_enumerate().
libusb HIDAPI programs are encouraged to use the interface number
instead to differentiate between interfaces on a composite HID device. */
/*#define INVASIVE_GET_USAGE*/

Although the documentation recommends to use interface number, for the hardware I'm testing on, interface number is the same between devices. How do other users handle edge-cases where HID returns two device matches on the same physical device on Linux?

@todbot
Copy link

todbot commented Mar 21, 2018

It sounds like you're using the 'libusb' driver on Linux.
The libusb Linux driver does not have usage and usagePage properties, but the hidraw Linux driver does. You should be able to switch the driver for your app and have it still work.

Note you'll need to change your udev rules if you're using those, swapping KERNEL=="hidraw*" for SUBSYSTEM=="usb".

@tresf
Copy link
Author

tresf commented Mar 21, 2018

@todbot yes, I believe I am. I'm using it indirectly through a third party, so I'll have to see if switching is an option. Thanks.

@todbot
Copy link

todbot commented Mar 21, 2018

The hid4java's build process is pretty foreign to me. I can't see how hidapi is even being compiled from the docs for hid4java, making me think he hand-compiles them and then copies them over.

If that's the case, I would try hand-compiling hidapi and copying the file yourself. The README gives how to do that, but in summary, on Linux it would be:

sudo apt-get install libudev-dev autotools-dev autoconf automake libtool build-essential
git clone https://github.com/signal11/hidapi
cd hidapi
./bootstrap
./configure --prefix=${HOME}/hidapi_tmp
make 
make install

And then you'll have a libhidapi_tmp/lib/libhidapi-hidraw.so.0.0.0 file.
Copy that file on top of the file hid4java/src/main/resources/linux-x86/libhidapi.so

@tresf
Copy link
Author

tresf commented Mar 22, 2018

@todbot thanks kindly for this information! What's not immediately obvious is why the libusb-1.0-0, libusb-1.0-0-dev are left out... or more specifically... how to build without them. How does the build system know to use hidraw, or does the target provide both when done?

@tresf
Copy link
Author

tresf commented Mar 22, 2018

does the target provide both when done?

Answering my own question, libusb-1.0-0 libusb-1.0-0-dev required and yes, both libraries are built.

@todbot I have to thank you for going out of your way to look into the 3rd party library, that's very kind.

So I've replaced /linux-x86-64/libhidapi.so in hid4java-0.5.0.jar with libhidapi-hidraw.so.0.0.0 and I can confirm that UsagePage is returned, but there's some disparity...

Endpoint 1 Endpoint 2
MacOS UsagePage -116 140
Windows UsagePage -116 140
Linux UsagePage 0 14776

Is there some translation that can be used to map these values to each other? Grabbing at straws here. :)

Note you'll need to change your udev rules if you're using those, swapping KERNEL=="hidraw*" for SUBSYSTEM=="usb"

We've been using SUBSYSTEM=="usb" historically. For some odd reason, this machine works (standard user, not root) without the rules I usually install. It's running VirtualBox VM with Guest Additions, device attached as same user.

ubuntu@ubuntu1404:~$ cat /etc/udev/rules.d/*.rules 
# libusb device access
SUBSYSTEM=="usb_device", ACTION=="add", RUN+="/usr/bin/killall -sUSR1 portcommunicationserviced"
SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="/usr/bin/killall -sUSR2 portcommunicationserviced"
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="/usr/bin/killall -sUSR1 portcommunicationserviced"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="/usr/bin/killall -sUSR2 portcommunicationserviced"
KERNEL=="vboxguest", NAME="vboxguest", OWNER="vboxadd", MODE="0660"
KERNEL=="vboxuser", NAME="vboxuser", OWNER="vboxadd", MODE="0666"

@tresf
Copy link
Author

tresf commented Mar 22, 2018

Tested UsagePage on physical hardware (identical OS, NOT in a VM) and received different and even less useful results:

Endpoint 1 Endpoint 2
MacOS UsagePage -116 140
Windows UsagePage -116 140
Linux UsagePage (VM) 0 14776
Linux UsagePage (Physical) 18432 18432

@jleni
Copy link

jleni commented Aug 5, 2018

I could solve the problem of zero values by moving to hidraw. However, I now receive odd/incorrect numbers.

@tresf Could you find a solution to this problem?
I have seeing something similar. Actually, same device, same host, different libraries show the following:

If I use https://github.com/flynn/hid
path: /dev/hidraw5
VendorID : 0x2c97
UsagePage : 0xffa0

However, when I use a library that is signal11 based:

path: "/dev/hidraw5",
vendor_id: 0x2c97,
usage_page: 0x0032

@tresf
Copy link
Author

tresf commented Aug 5, 2018

Unfortunately no. We (my project) simply cannot support this type of hardware on Linux using the hidapi library.

@jleni
Copy link

jleni commented Aug 9, 2018

it seems to me that the usage_page is not even set and the values we are seeing are some left over.

hidapi/linux/hid.c

Lines 479 to 555 in a6a622f

cur_dev->vendor_id = dev_vid;
cur_dev->product_id = dev_pid;
/* Serial Number */
cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8);
/* Release Number */
cur_dev->release_number = 0x0;
/* Interface Number */
cur_dev->interface_number = -1;
switch (bus_type) {
case BUS_USB:
/* The device pointed to by raw_dev contains information about
the hidraw device. In order to get information about the
USB device, get the parent device with the
subsystem/devtype pair of "usb"/"usb_device". This will
be several levels up the tree, but the function will find
it. */
usb_dev = udev_device_get_parent_with_subsystem_devtype(
raw_dev,
"usb",
"usb_device");
if (!usb_dev) {
/* Free this device */
free(cur_dev->serial_number);
free(cur_dev->path);
free(cur_dev);
/* Take it off the device list. */
if (prev_dev) {
prev_dev->next = NULL;
cur_dev = prev_dev;
}
else {
cur_dev = root = NULL;
}
goto next;
}
/* Manufacturer and Product strings */
cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]);
cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
/* Release Number */
str = udev_device_get_sysattr_value(usb_dev, "bcdDevice");
cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
/* Get a handle to the interface's udev node. */
intf_dev = udev_device_get_parent_with_subsystem_devtype(
raw_dev,
"usb",
"usb_interface");
if (intf_dev) {
str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
}
break;
case BUS_BLUETOOTH:
/* Manufacturer and Product strings */
cur_dev->manufacturer_string = wcsdup(L"");
cur_dev->product_string = utf8_to_wchar_t(product_name_utf8);
break;
default:
/* Unknown device type - this should never happen, as we
* check for USB and Bluetooth devices above */
break;
}
}

@jleni
Copy link

jleni commented Aug 9, 2018

Actually, it seems that here is a dead PR with the fix:

#6

It is unfortunate that the project has no activity since 2016

@jleni
Copy link

jleni commented Aug 9, 2018

@tresf would you mind renaming the issue to: "Invalid usage_page values in Linux" ?

@tresf tresf changed the title Help distinguishing endpoints Invalid usage_page values in Linux Aug 9, 2018
@tresf
Copy link
Author

tresf commented Aug 9, 2018

@tresf would you mind renaming the issue to: "Invalid usage_page values in Linux" ?

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants