Skip to content
Gary Rowe edited this page Apr 16, 2024 · 17 revisions

Introduction

The following are known issues and their solutions or workarounds.

You may find some of the following commands useful during your debugging process:

Enumerate USB devices with device details

Linux:

lsusb -v

macOS:

ioreg -lfxp IOUSB

Monitor udev rules on Linux

udevadm monitor

General problems

The hidapi native library doesn't load for my platform

On startup hid4java will search the classpath looking for a library that matches the machine OS and architecture (e.g. Windows running on AMD64). It uses the JNA naming conventions to do this and will report the expected path if it fails. Supported platforms include:

  • darwin-x86-64 - macOS 64-bit
  • darwin-aarch64 - macOS ARM64
  • linux-aarch64 - Linux ARMv8 64-bit only
  • linux-amd64 - Linux AMD 64-bit only
  • linux-arm - Linux ARMv7 hard float 32-bit only
  • linux-armel - Linux ARMv5 soft float 32-bit
  • linux-riscv64 - Linux RISC-V 64-bit
  • linux-x86-64 - Linux x86 64-bit only
  • linux-x86 - Linux x86 32-bit only
  • win32-x86 - Windows 32-bit only
  • win32-x86-64 - Windows 64-bit only
  • win32-aarch64 - Windows 64-bit ARM64

You can add your own entry under src/main/resources and it should get picked up. Ideally you should raise an issue on the hid4java repo so that the proper library can be put into the project so that others can avoid this problem.

If you would like to cross-compile hidapi for your platform, please refer to these step-by-step instructions.

My device doesn't work

Check that the usage page is not 0x06 which is reserved for keyboards and mice. Windows opens these devices for its exclusive use and thus hid4java cannot establish its own connection to them.

You will most likely need to use the lower level usb4java library for this as it is based on the libusb 1.0 native libraries. For more details on using libusb, particularly on Windows, have a read of this section of their documentation.

I don't see any attach events on startup

This is the default behaviour and has been maintained for backward compatibility (0.6.0 and below). From 0.7.0 onwards the HidSpecification allows for a manual start (which was implied but not the actual behaviour) so that any attached devices can announce their presence immediately.

// Configure to use custom specification
HidServicesSpecification hidServicesSpecification = new HidServicesSpecification();

// Use manual start feature to get immediate attach events
hidServicesSpecification.setAutoStart(false);

// Get HID services
HidServices hidServices = HidManager.getHidServices(hidServicesSpecification);
hidServices.addHidServicesListener(this);

// Manually start the services to get attachment event
hidServices.start();

My device is getting overloaded with hid4java enumeration requests

In order to detect if a device is attached or not hid4java must periodically scan the attached devices list and compare them to its internal manifest. By default this is done at a fixed interval of 500ms. However some devices that take time to process data can become overloaded and so need "quiet time" to respond to a write request. To set this use

  • HidSpecification.scanMode - the mode (no scanning, fixed interval, fixed interval with pause after write)
  • HidSpecification.scanInterval - the time between enumeration scans when free running
  • HidSpecification.pauseInterval - the time to pause until returning to free running until the next write occurs

By choosing an appropriate configuration from the above settings you should be able to reduce the enumeration load on your device.

// Configure to use custom specification
HidServicesSpecification hidServicesSpecification = new HidServicesSpecification();

// Use the fixed interval with pause after write to allow device to process data
// without being interrupted by enumeration requests 
// (the default pause of 5000ms is sufficient for device and UX)
hidServicesSpecification.setScanMode(ScanMode.SCAN_AT_FIXED_INTERVAL_WITH_PAUSE_AFTER_WRITE);

I get a SIGSEGV (0xb) when starting up

This type of error is thrown by the Java Virtual Machine when a low level device library causes a problem.

One example of this is when JNA interacts with the hidapi native library. If, for example, the getFieldOrder list is given in the wrong order then the offsets used to find the exposed functions in the native library are calculated incorrectly and the JVM crashes. (In this case hid4java uses the field list from Class.getFields() to ensure the correct order.

Another cause is if a Structure has not been initialised and is being dereferenced, perhaps in a toString() method.

Outside of the hid4java operations, your application may be introducing USB conflicts - perhaps between hidapi and libusb. One approach is to choose which library will interact with which devices and then ensure that minimal overlap occurs. Perhaps hid4java is scanning for devices (for attach/detach events) which could be handled by the other library. You can use ScanMode.NO_SCAN to stop those events.

Further information on debugging low level messages from the JVM can be found in this StackOverflow answer.

Windows

The hidapi library loads but takes a long time

You have probably terminated the JVM using a kill -9 rather than a clean shutdown. This will have left the HidApi process lock on the DLL still in force and Windows will continuously check to see if it can share it with a new instance. Just detach and re-attach the device to clear it.

Another explanation is that another process has grabbed the USB HID and has not released it. Check your task manager.

Finally, it may be that another process has gained an exclusive lock on the hidapi native library (perhaps directly or via another JNA process) and it may require a reboot of Windows to ultimately clear it.

I'm seeing spurious attach/detach events occurring on Windows

This was a device enumeration bug in early versions of hid4java. Use version 0.3.1 or higher.

I get a "The parameter is incorrect" when writing

If you're seeing this then you should update hid4java to the latest version.

The mouse pointer freezes every so often

This is a known issue with some mouse devices (e.g. Scorpion Marvo series) on Windows 10. The calling hidServices.scan() method freezes the mouse pointer and there is currently no workaround (all scan modes give the same result). Standard USB mice do not have this issue.

Thanks to Brezgil for this catch.

Linux

How USB devices are mapped in Linux

In general there are two main types of device nodes in Linux: device drivers and raw device nodes. The first kind, such as a USB mass storage device would be mapped as /dev/sdb. The second kind are general purpose raw USB devices. You will usually find references to hidraw devices under /dev/hidrawX where X is a number generated by udev which is the userspace device manager for the Linux kernel (#include <libudev.h in C). These raw devices are mapped as /dev/bus/usb/BBB/DDD where BBB is the bus number and DDD is the device number. Using this approach bypasses the kernel driver.

Setting your own rules

Since a userspace program is acting like a device driver it has obvious security concerns and thus permissions need to be set correctly. By default, all raw USB device programs have 0664 permissions and need to have an entry under /etc/udev/rules.d ending in .rules. For example, /etc/udev/rules.d/99-myhid.rules.

Typically when creating your .rules file you will need the vendorId and productId. These can be found using lsusb and examining the output for ID xxxx:yyyy. xxxx maps to vendorId, yyyy maps to productId.

See this StackExchange answer on udev for more details on setting rules. You may also find this introduction helpful.

Mapping /dev/hidraw to /dev/bus/usb/BBB/DDD

Sometimes it is useful to determine which device under /dev/hidrawX is mapped to which device in /dev/bus/usb/BBB/DDD. This is non-trivial. You can start by finding BBB and DDD using lsusb. The mapping to X is provided through libudev directly and will require compiling a utility app.

See USB device issues in Linux From Scratch for more information.

My device doesn't work on Linux

Different flavours of Linux require different settings:

Ubuntu

Out of the box Ubuntu classifies HID devices as belonging to root. You can override this rule by creating your own under /etc/udev/rules.d:

sudo gedit /etc/udev/rules.d/99-myhid.rules

Make the content of this file as below (using your own discovered hex values for idVendor and idProduct in lowercase with no 0x prefix):

# My HID device
KERNEL=="hidraw*", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="abcd",  MODE="0666", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl"

(The TAG entries are there for compatibility with systemd). You may find that you need to finalise MODE with MODE:="0666" as seen in issue #106 on Mint Linux (a Debian/Ubuntu variant).

Save and exit from root, then unplug and replug your device. The rules should take effect immediately.

If they're still not running it may be that you're not a member of the plugdev group. You can fix this as follows (assuming that plugdev is not present on your system):

sudo addgroup plugdev
sudo addgroup yourusername plugdev

Slackware

Edit the USB udev rules /etc/udev/rules.d as follows:

MODE="0666", GROUP="dialout"

ARM

Running on ARM machines you may encounter problems due to a missing library. This is just a naming issue for the udev library and can be resolved using the following command (or equivalent for your system):

sudo ln -sf /lib/arm-linux-gnueabihf/libudev.so.1 /lib/arm-linux-gnueabihf/libudev.so.0

Thanks to @MaxRoma for that one!

My device is added then immediately removed on Ubuntu

This appears to be an issue with fwupd on Ubuntu 16.0. As it is fixed in Ubuntu 18.0+ it is probably worth upgrading to that version.

However, if you cannot upgrade then a workaround is available in issue #97.

Thanks to @Laivindur for their detailed investigation.

I want to choose between libusb and hidraw variants on Linux

The hidapi Linux support library is available in two variants: libusb and hidraw. In general the hidraw variant is the most flexible and it allows Bluetooth interfaces to be addressed. However, you can force the use of the older libusb as follows (the default is hidraw):

HidApi.useLibUsbVariant = true

Setting this parameter will enable libusb libraries (which have slightly different behaviour) when executing on a Linux platform.