hidapi
Loading...
Searching...
No Matches
test.c

contains a basic example usage of the HIDAPI library.

/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
Alan Ott
Signal 11 Software
libusb/hidapi Team
Copyright 2022.
This contents of this file may be used by anyone
for any reason without any conditions and may be
used as a starting point for your own applications
which use HIDAPI.
********************************************************/
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <hidapi.h>
// Headers needed for sleeping.
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
// Fallback/example
#ifndef HID_API_MAKE_VERSION
#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p))
#endif
#ifndef HID_API_VERSION
#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
#endif
//
// Sample using platform-specific headers
#if defined(__APPLE__) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
#include <hidapi_darwin.h>
#endif
#if defined(_WIN32) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
#include <hidapi_winapi.h>
#endif
#if defined(USING_HIDAPI_LIBUSB) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
#include <hidapi_libusb.h>
#endif
//
const char *hid_bus_name(hid_bus_type bus_type) {
static const char *const HidBusTypeName[] = {
"Unknown",
"USB",
"Bluetooth",
"I2C",
"SPI",
};
if ((int)bus_type < 0)
bus_type = HID_API_BUS_UNKNOWN;
if ((int)bus_type >= (int)(sizeof(HidBusTypeName) / sizeof(HidBusTypeName[0])))
bus_type = HID_API_BUS_UNKNOWN;
return HidBusTypeName[bus_type];
}
void print_device(struct hid_device_info *cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
printf("\n");
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
printf(" Product: %ls\n", cur_dev->product_string);
printf(" Release: %hx\n", cur_dev->release_number);
printf(" Interface: %d\n", cur_dev->interface_number);
printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page);
printf(" Bus type: %u (%s)\n", (unsigned)cur_dev->bus_type, hid_bus_name(cur_dev->bus_type));
printf("\n");
}
void print_hid_report_descriptor_from_device(hid_device *device) {
unsigned char descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
int res = 0;
printf(" Report Descriptor: ");
res = hid_get_report_descriptor(device, descriptor, sizeof(descriptor));
if (res < 0) {
printf("error getting: %ls", hid_error(device));
}
else {
printf("(%d bytes)", res);
}
for (int i = 0; i < res; i++) {
if (i % 10 == 0) {
printf("\n");
}
printf("0x%02x, ", descriptor[i]);
}
printf("\n");
}
void print_hid_report_descriptor_from_path(const char *path) {
hid_device *device = hid_open_path(path);
if (device) {
print_hid_report_descriptor_from_device(device);
hid_close(device);
}
else {
printf(" Report Descriptor: Unable to open device by path\n");
}
}
void print_devices(struct hid_device_info *cur_dev) {
for (; cur_dev; cur_dev = cur_dev->next) {
print_device(cur_dev);
}
}
void print_devices_with_descriptor(struct hid_device_info *cur_dev) {
for (; cur_dev; cur_dev = cur_dev->next) {
print_device(cur_dev);
print_hid_report_descriptor_from_path(cur_dev->path);
}
}
int main(int argc, char* argv[])
{
(void)argc;
(void)argv;
int res;
unsigned char buf[256];
#define MAX_STR 255
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
struct hid_device_info *devs;
printf("hidapi test/example tool. Compiled with hidapi version %s, runtime version %s.\n", HID_API_VERSION_STR, hid_version_str());
printf("Compile-time version matches runtime version of hidapi.\n\n");
}
else {
printf("Compile-time version is different than runtime version of hidapi.\n]n");
}
if (hid_init())
return -1;
#if defined(__APPLE__) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
// To work properly needs to be called before hid_open/hid_open_path after hid_init.
// Best/recommended option - call it right after hid_init.
hid_darwin_set_open_exclusive(0);
#endif
devs = hid_enumerate(0x0, 0x0);
print_devices_with_descriptor(devs);
// Set up the command buffer.
memset(buf,0x00,sizeof(buf));
buf[0] = 0x01;
buf[1] = 0x81;
// Open the device using the VID, PID,
// and optionally the Serial number.
handle = hid_open(0x4d8, 0x3f, NULL);
if (!handle) {
printf("unable to open device\n");
return 1;
}
// Read the Manufacturer String
wstr[0] = 0x0000;
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read manufacturer string\n");
printf("Manufacturer String: %ls\n", wstr);
// Read the Product String
wstr[0] = 0x0000;
res = hid_get_product_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read product string\n");
printf("Product String: %ls\n", wstr);
// Read the Serial Number String
wstr[0] = 0x0000;
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read serial number string\n");
printf("Serial Number String: (%d) %ls\n", wstr[0], wstr);
print_hid_report_descriptor_from_device(handle);
struct hid_device_info* info = hid_get_device_info(handle);
if (info == NULL) {
printf("Unable to get device info\n");
} else {
print_devices(info);
}
// Read Indexed String 1
wstr[0] = 0x0000;
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
if (res < 0)
printf("Unable to read indexed string 1\n");
printf("Indexed String 1: %ls\n", wstr);
// Set the hid_read() function to be non-blocking.
hid_set_nonblocking(handle, 1);
// Try to read from the device. There should be no
// data here, but execution should not block.
res = hid_read(handle, buf, 17);
// Send a Feature Report to the device
buf[0] = 0x2;
buf[1] = 0xa0;
buf[2] = 0x0a;
buf[3] = 0x00;
buf[4] = 0x00;
res = hid_send_feature_report(handle, buf, 17);
if (res < 0) {
printf("Unable to send a feature report.\n");
}
memset(buf,0,sizeof(buf));
// Read a Feature Report from the device
buf[0] = 0x2;
res = hid_get_feature_report(handle, buf, sizeof(buf));
if (res < 0) {
printf("Unable to get a feature report: %ls\n", hid_error(handle));
}
else {
// Print out the returned buffer.
printf("Feature Report\n ");
for (i = 0; i < res; i++)
printf("%02x ", (unsigned int) buf[i]);
printf("\n");
}
memset(buf,0,sizeof(buf));
// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
buf[0] = 0x1;
buf[1] = 0x80;
res = hid_write(handle, buf, 17);
if (res < 0) {
printf("Unable to write(): %ls\n", hid_error(handle));
}
// Request state (cmd 0x81). The first byte is the report number (0x1).
buf[0] = 0x1;
buf[1] = 0x81;
hid_write(handle, buf, 17);
if (res < 0) {
printf("Unable to write()/2: %ls\n", hid_error(handle));
}
// Read requested state. hid_read() has been set to be
// non-blocking by the call to hid_set_nonblocking() above.
// This loop demonstrates the non-blocking nature of hid_read().
res = 0;
i = 0;
while (res == 0) {
res = hid_read(handle, buf, sizeof(buf));
if (res == 0) {
printf("waiting...\n");
}
if (res < 0) {
printf("Unable to read(): %ls\n", hid_error(handle));
break;
}
i++;
if (i >= 10) { /* 10 tries by 500 ms - 5 seconds of waiting*/
printf("read() timeout\n");
break;
}
#ifdef _WIN32
Sleep(500);
#else
usleep(500*1000);
#endif
}
if (res > 0) {
printf("Data read:\n ");
// Print out the returned buffer.
for (i = 0; i < res; i++)
printf("%02x ", (unsigned int) buf[i]);
printf("\n");
}
hid_close(handle);
/* Free static HIDAPI objects. */
#ifdef _WIN32
system("pause");
#endif
return 0;
}
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
Set the device handle to be non-blocking.
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.
hid_bus_type
HID underlying bus types.
Definition: hidapi.h:122
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
Get a string from a HID device, based on its string index.
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
Read an Input report from a HID device.
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_get_device_info(hid_device *dev)
Get The struct hid_device_info from a HID device.
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
Get The Serial Number String from a HID device.
#define HID_API_MAX_REPORT_DESCRIPTOR_SIZE
Maximum expected HID Report descriptor size in bytes.
Definition: hidapi.h:103
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
Get The Product String from a HID device.
HID_API_EXPORT hid_device *HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number.
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
Get The Manufacturer String from a HID device.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
Close a HID device.
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path)
Open a HID device by its path name.
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
Get a feature report from a HID device.
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
Write an Output report to a HID device.
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size)
Get a report descriptor from a HID device.
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *dev)
Get a string describing the last error which occurred.
#define HID_API_VERSION_STR
Static/compile-time string version of the library.
Definition: hidapi.h:95
HID_API_EXPORT const char *HID_API_CALL hid_version_str(void)
Get a runtime version string of the library.
int HID_API_EXPORT HID_API_CALL hid_exit(void)
Finalize the HIDAPI library.
#define HID_API_VERSION
Static/compile-time version of the library.
Definition: hidapi.h:89
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
Send a Feature report to the device.
HID_API_EXPORT const struct hid_api_version *HID_API_CALL hid_version(void)
Get a runtime version of the library.
#define HID_API_MAKE_VERSION(mj, mn, p)
Coverts a version as Major/Minor/Patch into a number: <8 bit major><16 bit minor><8 bit patch>.
Definition: hidapi.h:79
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
@ HID_API_BUS_UNKNOWN
Definition: hidapi.h:124
struct hid_device_ hid_device
Definition: hidapi.h:116
Definition: hidapi.h:150
unsigned short product_id
Definition: hidapi.h:156
struct hid_device_info * next
Definition: hidapi.h:181
unsigned short usage
Definition: hidapi.h:171
wchar_t * manufacturer_string
Definition: hidapi.h:163
unsigned short vendor_id
Definition: hidapi.h:154
char * path
Definition: hidapi.h:152
unsigned short release_number
Definition: hidapi.h:161
wchar_t * serial_number
Definition: hidapi.h:158
int interface_number
Definition: hidapi.h:178
unsigned short usage_page
Definition: hidapi.h:168
wchar_t * product_string
Definition: hidapi.h:165
hid_bus_type bus_type
Definition: hidapi.h:186