Enumerating Devices
libhid provides for both synchronous and asynchronous device discovery. To use the synchronous interface, call HID::find()
with an optional filter set. The call will return a list of device objects that match the filters. If no filters were given, all available devices are returned.
The asynchronous interface is built around an enumerator class. An instance of the enumerator class can be used to discover connected devices and receive notifications when devices are attached or removed. If provided with a set of filters the enumerator will only generate notifications for devices that match the filters.
Finding Devices
#include <hid.h>;
HID::filter::And filters;
filters.push_back(new VendorID(VENDOR_ID));
filters.push_back(new ProductID(PRODUCT_ID));
// Get a list of available devices matching both PRODUCT_ID and VENDOR_ID
HID::device_list devices = HID::find(&filters);
// Display each device's product string on the console
HID::device_list::iterator i = devices.begin();
for(; i != devices.end(); ++i)
printf("Found device %s\n", (*i)->product().c_str());
The Enumerator
#include <hid.h>;
void deviceAttach(HID::enumerator_type* enumerator, HID::device_type* device, void* context)
{
printf("Found device %s\n", device->product().c_str());
}
void deviceRemoval(HID::enumerator_type* enumerator, HID::device_type* device, void* context)
{
printf("Lost device %s\n", device->product().c_str());
}
// Create a simple filter object
HID::filter::And filters;
filters.push_back(new VendorID(VENDOR_ID));
filters.push_back(new ProductID(PRODUCT_ID));
// Create an enumerator and register callbacks
HID::enumerator_type enumerator(&filters);
enumerator.setMatchCallback(deviceAttach);
enumerator.setRemovalCallback(deviceRemoval);
if( enumerator->start() )
{
printf("started the enumerator\n");
// Start an event loop and block (only needed for console apps)
HID::run();
}
Note that on win32, if the device isn’t already open, calling device->product()
will automatically open the device read-only, get the product string, and then close the device. If the device was already open it will remain open after the call to device->product()
.
Opening Devices
Once a particular device has been found (either using HID::find()
or a HID::enumerator_type
), the resulting device object can be opened by calling its open()
method. By default, the device is opened in read-only mode. To open the device in write-only mode, pass HID::WriteMode
to ‘open()’.
#include <hid.h>;
// Get a list of all available devices
HID::device_list devices = HID::find();
if( devices.size() )
{
// Take the first device on the list
HID::device_type* device = devices.front();
// Open the device for writing
device->open(HID::WriteMode);
// Send the output report contained in buffer
HID::buffer_type buffer;
device->output(REPORT_ID, buffer);
// Close the device, just for fun
device->close();
// Let's open it again, but for reading this time
device->open(HID::ReadMode);
// Get an input report from the device and store it in buffer
buffer = device->input(REPORT_ID);
// Close it for good this time
device->close();
}
Of course, a device can be opened for both reading and writing by passing (HID::ReadMode | HID::WriteMode)
to open()
…
#include <hid.h>;
// Get a list of all available devices
HID::device_list devices = HID::find();
if( devices.size() )
{
// Take the first device on the list
HID::device_type* device = devices.front();
// Open the device for reading and writing
device->open(HID::ReadMode | HID::WriteMode);
// Send the output report contained in buffer
HID::buffer_type buffer;
device->output(REPORT_ID, buffer);
// Get an input report from the device and store it in buffer
buffer = device->input(REPORT_ID);
// We're finished with the device, so close it
device->close();
}