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;
}
}
}
}
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?
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.
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.
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);
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.
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.