#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>

static const char *dev_name = "/dev/usb/hiddev0";

typedef uint32_t __u32;
typedef int32_t __s32;

#define HID_REPORT_ID_UNKNOWN 0xffffffff

#define HIDIOCGUSAGES           _IOWR('H', 0x13, struct hiddev_usage_ref_multi)
#define HIDIOCSUSAGES           _IOW('H', 0x14, struct hiddev_usage_ref_multi)

#define HID_REPORT_TYPE_INPUT   1
#define HID_REPORT_TYPE_OUTPUT  2
#define HID_REPORT_TYPE_FEATURE 3
#define HID_REPORT_TYPE_MIN     1
#define HID_REPORT_TYPE_MAX     3

struct hiddev_usage_ref {
         __u32 report_type;
         __u32 report_id;
         __u32 field_index;
         __u32 usage_index;
         __u32 usage_code;
         __s32 value;
};

#define HID_MAX_MULTI_USAGES 1024
struct hiddev_usage_ref_multi {
         struct hiddev_usage_ref uref;
         __u32 num_values;
         __s32 values[HID_MAX_MULTI_USAGES];
};


int main(void)
{
	int fd;
	struct hiddev_usage_ref_multi dev = { 0 };
	uint32_t report_type, usage_code;
	fd = open(dev_name, O_RDWR);
	if (fd < 0) {
		printf("Failed to open %s with errno %s\n", dev_name, strerror(errno));
		return EXIT_FAILURE;
	}

	dev.num_values = 12345679;
	dev.uref.report_id = HID_REPORT_ID_UNKNOWN;

	for (report_type = 1; report_type < HID_REPORT_TYPE_MAX; report_type++) {
		dev.uref.report_type = report_type;
		for (usage_code = 0; usage_code < 0xFFFFFFF; usage_code++) {
			dev.uref.usage_code = usage_code;
			ioctl(fd, HIDIOCGUSAGES, &dev);
		}
	}
	return EXIT_FAILURE;
}
