JUCE Wrapper for HID API

Here is a JUCE C++ wrapper for the hidapi, a convenient library that interfaces with HID devices.

Thought it might be useful to someone!

There is a hid::DeviceScanner class that will notify you when a device is connected, a central DeviceIO class that does most of the dirty work without needing to touch the lower-level C API, and a few other helper classes & functions.

I will usually do something like this:

if (hid::isDeviceAvailable (MY_DEVICE_VID, MY_DEVICE_PID) {
    auto deviceInfo = hid::getDeviceInfo (MY_DEVICE_VID, MY_DEVICE_PID);
    auto deviceIO = deviceInfo.connect();
    deviceIO.setNonblocking (true);
 
    if (hid::isConnected()) {
        // write something to the device
        auto result = hid::getConnectedDevice().write (&dataToSend, numBytesToSend);
        if (! result.wasOk()) {
            DBG("Couldn't write to device: " << result.getErrorMessage());
        }

        // read something back - I set it to nonblocking above, so we need to poll it regularly
        // I usually do this on a timer thread, but whatever floats your boat
        while (true) {
            result = hid::getConnectedDevice().read (&dataToRead, numBytesToRead);
            if (result.wasOk()) {
                // Read some bytes from the device!
                break;
            }
        }
    }
}
6 Likes

Good idea, thanks! I use HIDAPI directly, so I’ll test your wrapper. Is there any important reason why Linux version is not included?

I never got around to needing it. Will be updating it with linux support soon, but it should be pretty easy to add the required libusb dependencies.

Has anybody used this is anger? I’m finding windows reporting huge numbers of memory leaks.

This library is just a wrapper for the HID API. I’ve been using this reliably on Windows to update firmware for a MIDI device. If you’re having issues with it, first try just using the raw HID API (it’s a well designed library), and if you’re still having issues, Signal11 (the guy who wrote it) seems to not be active online anymore, so it may be worthwhile to use the raw Windows API. That being said, I haven’t had issues with this on Windows so far - if there is a simple fix for your issue I’m happy to take a look. What is your use case?

I can send a VS19 project with the memory leaks. Will that do?

MinimalUSB.zip (79.5 KB)

For anyone still trying to use this project — it looks like there are some memory leaks on windows, and I don’t have the time to work on this right now. I’d recommend avoiding my JUCE wrapper for now if you are running into issues and just use HIDAPI directly.

That being said, if you want reference for how to use the HIDAPI, this repository can still be useful. Personally, I haven’t been running into any issues or memory leaks with this, so YMMV. However, all my development is on Mac & Linux.

I have tracked down the leaks, and they are a windos only issue. If we can communicate off forum about it I can let you know what I have found. As always with these things, the solution is quite simple, but tracking it down was a bitch.

Wow, thanks! I definitely appreciate the effort. I’ll message you & we can communicate.

I have just checked and I have memory leaks on Windows as well. I’d be happy help out testing any patches :slight_smile:

Just pushed the update to the repo!

Feel free to test it — I’m traveling and can’t test on windows at the moment unfortunately. Will be doing some more testing when I can.

Thanks! I will give this a go soon and see how it goes.

Seems to be working well on Windows for me. Thanks for your work!

Thanks for helping test!

As you know, I am a predominantly Windows coder, but I got the program I’ve written using the HID API to work perfectly on a Mac - even the latest version. I handed the app to our guy who builds install packages for Macs, and the resulting code does not ‘see’ any USB devices. It has been run through an Apple certification program, and the suspicion is that the HID code has been stripped out. Does this code have any official Apple certification, and why would Apple not like it?

I’ve been using this in production on the Mac app store for years now. I don’t think apple would have a problem with it, because it’s just a light wrapper for their native mac HID calls.

However, I could definitely see that happening anyway, because it’s Apple. I’d double check that your app asks for the right USB permissions. Apple has been making tons of breaking changes to macOS lately so it would not surprise me. But I also have since rebuilt and re-submitted the app very recently and it is live on the app store with the HID parts working as expected.

None of this works on iOS because they don’t let you do low level USB stuff on iOS devices for official apps.

1 Like

I was just trying out your JUCE wrapper on Mac, and it seems to be going ok. I can read raw bytes from a couple different devices.

However, I’m not getting useful results back from the getFeatureReport method, and I’m wondering what I’m missing. From one device there is no feature report data (the Result returned just says “Unknown Error”). From another device I get a short (6 byte) return from the getFeatureReport method.

If I understand how the whole HID system is supposed to work, it seems I’ll have a tough time correctly interpreting the raw output bytes from a device, if I can’t get the feature report data to help me interpret those bytes.

So… what am I missing? Am I supposed to encode something into that unsigned char buffer that getFeatureReport takes as its first argument? (currently, it’s just zeroed)

Result result = hid::getConnectedDevice().getFeatureReport (buffer, numBytesToRead, &numBytesRead); 

I would appreciate any pointers on that!

Hey, to followup on this after a bunch more research: The HID API cannot do what I want it to do (and so neither can the JUCE module/wrapper that @cpenny built around HID API).

What I wanted to do was to be able to connect any HID compliant device as the input to an app, and be able to map its controls to commands within the app. However, in order to do this in a “universal” way, I would need the HID Report Descriptor (which I think I was confusing above with a different thing called a “Feature Report”) from the device.

According to this StackOverflow answer, Alan Ott (who wrote the HID API) says:

HIDAPI does not provide functions for getting or parsing the report descriptor. Since HIDAPI is for talking to a custom devices, these devices will likely contain all or mostly vendor-defined report items anyway.

So there you have it.