--- /dev/null
+/**/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/types.h>
+#include <linux/hiddev.h>
+
+#include "common.h"
+
+#if 0
+static void dump(const void *pu, int l) {
+ const uint8_t *p= pu;
+ while (l>0) {
+ printf("%02x",*p++);
+ l--;
+ }
+ putchar(' ');
+}
+#endif
+
+static void report_scan(const char *which, int type) {
+ struct hiddev_report_info rinfo;
+ int r, i, j;
+ int fd=0;
+
+ rinfo.report_type = type;
+ rinfo.report_id = HID_REPORT_ID_FIRST;
+
+ for (;;) {
+ r = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+ if (r && errno==EINVAL) break;
+ if (r) diee("HIDIOCGREPORTINFO");
+
+ printf("%s type=%08"PRIx32" id=%08"PRIx32" num_fields=%08"PRIx32"\n",
+ which, rinfo.report_type, rinfo.report_id, rinfo.num_fields);
+ for (i=0; i < rinfo.num_fields; i++) {
+ struct hiddev_field_info finfo;
+ finfo.report_type= rinfo.report_type;
+ finfo.report_id= rinfo.report_id;
+ finfo.field_index= i;
+ r= ioctl(fd, HIDIOCGFIELDINFO, &finfo);
+ if (r) diee("HIDIOCGFIELDINFO");
+ printf("%s type=%08"PRIx32" id=%08"PRIx32" fi=%08"PRIx32
+ " maxusage=%08"PRIx32" flags=%08"PRIx32
+ " phys=%08"PRIx32"/log=%08"PRIx32"/app=%08"PRIx32
+ " log=%08"PRIx32"..%08"PRIx32
+ " phys=%08"PRIx32"..%08"PRIx32
+ "\n",
+ which, finfo.report_type, finfo.report_id, finfo.field_index,
+ finfo.maxusage, finfo.flags,
+ finfo.physical, finfo.logical, finfo.application,
+ finfo.logical_minimum, finfo.logical_maximum,
+ finfo.physical_minimum, finfo.physical_maximum
+ );
+ for (j=0; j < finfo.maxusage; j++) {
+ struct hiddev_usage_ref uref;
+ uref.report_type= finfo.report_type;
+ uref.report_id= finfo.report_id;
+ uref.field_index= i;
+ uref.usage_index= j;
+ r= ioctl(fd, HIDIOCGUCODE, &uref);
+//dump(&uref,sizeof(uref));
+ r= ioctl(fd, HIDIOCGUSAGE, &uref);
+//dump(&uref,sizeof(uref));
+ printf("%s type=%08"PRIx32" id=%08"PRIx32" fi=%08"PRIx32
+ " ui=%08"PRIx32" uc=%08"PRIx32" val=%08"PRIx32"\n",
+ which, uref.report_type, uref.report_id, uref.field_index,
+ uref.usage_index, uref.usage_code, uref.value);
+ }
+ }
+ rinfo.report_id |= HID_REPORT_ID_NEXT;
+ }
+}
+
+void die_vprintf_hook(const char *fmt, va_list al) { }
+void die_hook(void) { }
+const char *progname= "hiddev-ioctl";
+
+int main(int argc, char **argv) {
+ int r;
+ if (!argv[0] || !argv[1]) badusage("too few args");
+ const char *act= *++argv;
+ if (!strcmp(act, "scan")) {
+ report_scan("input", HID_REPORT_TYPE_INPUT);
+ report_scan("output", HID_REPORT_TYPE_OUTPUT);
+ } else if (!strcmp(act, "send")) {
+ /* type id field val */
+ if (!argv[1] || !argv[2] || !argv[3] || !argv[4]
+ || !argv[5] || !argv[6] || argv[7])
+ badusage("wrong # args");
+ struct hiddev_usage_ref uref;
+ struct hiddev_report_info rinfo;
+ uref.report_type= strtoul(argv[1],0,0);
+ uref.report_id= strtoul(argv[2],0,0);
+ uref.field_index= strtoul(argv[3],0,0);
+ uref.usage_index= strtoul(argv[4],0,0);
+ uref.usage_code= strtoul(argv[5],0,0);
+ uref.value= strtol(argv[6],0,0);
+ rinfo.report_type= uref.report_type;
+ rinfo.report_id= uref.report_id;
+ rinfo.num_fields= 0;
+// r= ioctl(0, HIDIOCGREPORT, &rinfo); if (r) diee("HIDIOCGREPORT");
+// r= ioctl(0, HIDIOCGUSAGE, &uref); if (r) diee("HIDIOCGUSAGE");
+//dump(&uref,sizeof(uref));
+// printf("%08"PRIx32"...",uref.value);
+ r= ioctl(0, HIDIOCSUSAGE, &uref); if (r) diee("HIDIOCSUSAGE");
+ r= ioctl(0, HIDIOCSREPORT, &rinfo); if (r) diee("HIDIOCSREPORT");
+ } else {
+ badusage("unknown action");
+ }
+ return 0;
+}
--- /dev/null
+/**/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/types.h>
+
+#include "hidraw.h"
+
+#include "common.h"
+
+static void dump(const void *pu, int l) {
+ const uint8_t *p= pu;
+ while (l>0) {
+ printf("%02x",*p++);
+ l--;
+ }
+ putchar(' ');
+}
+
+int main(int argc, char **argv) {
+ int r, descsz;
+
+ r= ioctl(0, HIDIOCGRDESCSIZE, &descsz);
+ if (r) {
+ perror("HIDIOCGRDESCSIZE");
+ } else {
+ printf("%d\n",descsz);
+ struct {
+ struct hidraw_report_descriptor d;
+ unsigned char buf[descsz];
+ } d;
+ d.d.size = descsz;
+ r= ioctl(0, HIDIOCGRDESC, &d);
+ if (r) perror("HIDIOCGRDESC");
+ else { dump(d.d.value, d.d.size); putchar('\n'); }
+ }
+
+ struct hidraw_devinfo di;
+ r= ioctl(0, HIDIOCGRAWINFO, &di);
+ if (r) perror("HIDIOCGRAWINFO");
+ else {
+ printf("%08"PRIx32" %04"PRIx16" %04"PRIx16"\n",
+ di.bustype, di.vendor, di.product);
+ }
+
+ unsigned char buf[PATH_MAX];
+
+ r= ioctl(0, HIDIOCGRAWNAME(PATH_MAX), buf);
+ if (r<0) perror("HIDIOCGRAWNAME");
+ else printf("%d %.*s\n", r, r,buf);
+
+ r= ioctl(0, HIDIOCGRAWPHYS(PATH_MAX), buf);
+ if (r<0) perror("HIDIOCGRAWPHYS");
+ else printf("%d %.*s\n", r, r,buf);
+
+ return 0;
+}
--- /dev/null
+#ifndef _HIDRAW_H
+#define _HIDRAW_H
+
+/*
+ * Copyright (c) 2007 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/hid.h>
+#include <linux/types.h>
+
+struct hidraw_report_descriptor {
+ __u32 size;
+ __u8 value[HID_MAX_DESCRIPTOR_SIZE];
+};
+
+struct hidraw_devinfo {
+ __u32 bustype;
+ __s16 vendor;
+ __s16 product;
+};
+
+/* ioctl interface */
+#define HIDIOCGRDESCSIZE _IOR('H', 0x01, int)
+#define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor)
+#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
+#define HIDIOCGRAWNAME(len) _IOC(_IOC_READ, 'H', 0x04, len)
+#define HIDIOCGRAWPHYS(len) _IOC(_IOC_READ, 'H', 0x05, len)
+
+#define HIDRAW_FIRST_MINOR 0
+#define HIDRAW_MAX_DEVICES 64
+/* number of reports to buffer */
+#define HIDRAW_BUFFER_SIZE 64
+
+
+/* kernel-only API declarations */
+#ifdef __KERNEL__
+
+struct hidraw {
+ unsigned int minor;
+ int exist;
+ int open;
+ wait_queue_head_t wait;
+ struct hid_device *hid;
+ struct device *dev;
+ struct list_head list;
+};
+
+struct hidraw_report {
+ __u8 *value;
+ int len;
+};
+
+struct hidraw_list {
+ struct hidraw_report buffer[HIDRAW_BUFFER_SIZE];
+ int head;
+ int tail;
+ struct fasync_struct *fasync;
+ struct hidraw *hidraw;
+ struct list_head node;
+ struct mutex read_mutex;
+};
+
+#ifdef CONFIG_HIDRAW
+int hidraw_init(void);
+void hidraw_exit(void);
+void hidraw_report_event(struct hid_device *, u8 *, int);
+int hidraw_connect(struct hid_device *);
+void hidraw_disconnect(struct hid_device *);
+#else
+static inline int hidraw_init(void) { return 0; }
+static inline void hidraw_exit(void) { }
+static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
+static inline int hidraw_connect(struct hid_device *hid) { return -1; }
+static inline void hidraw_disconnect(struct hid_device *hid) { }
+#endif
+
+#endif
+
+#endif